package com.jwgf.smarowindingmachine_unity.logic;

import com.alibaba.fastjson.JSON;
import com.jwgf.Half485.modbusthreadpool.PLCData;
import com.jwgf.common.AppContext;
import com.jwgf.fram.FramManager;
import com.jwgf.group.Group;
import com.jwgf.group.GroupMap;
import com.jwgf.objectbox.CbfReport;
import com.jwgf.objectbox.CbfReport_;
import com.jwgf.objectbox.FaultCounter;
import com.jwgf.objectbox.FaultCounter_;
import com.jwgf.objectbox.FaultRecord;
import com.jwgf.objectbox.FaultRecord_;
import com.jwgf.objectbox.GroupInfo;
import com.jwgf.objectbox.GroupInfo_;
import com.jwgf.objectbox.HeadReport;
import com.jwgf.objectbox.HeadReport_;
import com.jwgf.objectbox.ObjectBox;
import com.jwgf.objectbox.ProcessCounter;
import com.jwgf.objectbox.ProcessCounter_;
import com.jwgf.objectbox.ProcessRecord;
import com.jwgf.objectbox.ProcessRecord_;
import com.jwgf.objectbox.RedLightCounter;
import com.jwgf.objectbox.RedLightCounter_;
import com.jwgf.objectbox.RedLightRecord;
import com.jwgf.objectbox.RedLightRecord_;
import com.jwgf.objectbox.ShiftReport;
import com.jwgf.objectbox.ShiftReport_;
import com.jwgf.objectbox.SpindleParameter;
import com.jwgf.objectbox.StatisticRecord;
import com.jwgf.objectbox.StatisticRecord_;
import com.jwgf.objectbox.TubeRecord;
import com.jwgf.objectbox.TubeRecord4E;
import com.jwgf.objectbox.TubeRecord4E_;
import com.jwgf.objectbox.TubeRecord_;
import com.jwgf.report.ShiftTimeRule;
import com.jwgf.smarowindingmachine_unity.R;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

import io.objectbox.Box;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.functions.Consumer;

/**
 * @author Administrator
 * @describe
 */
public class Report { // 报表信息
    private FramManager fm = FramManager.getInstance();
    private static final int MAX_SPINDLE_NUM = 72;

    // 0x61
    private static int[] YARN_JOINTS = new int[MAX_SPINDLE_NUM];// 接头数
    private static int[] SPLICE_CYCLES = new int[MAX_SPINDLE_NUM];// 粘接次数
    private static int[] NUMBER_COPS_CHANGE = new int[MAX_SPINDLE_NUM];// 更换纱管数
    private static long[] SPLICE_TOTAL_TIME = new long[MAX_SPINDLE_NUM];// 接头总时间

    //0x64 DB
    private static int[] TUBE_LENGTH = new int[MAX_SPINDLE_NUM];// 管纱长度
    //0x65
    private static int[] SPLICES_RIGHT_FIRST_TIME = new int[MAX_SPINDLE_NUM];// 一次捻接成功数

    // 0x62
    // 0x62DB.0--0x62DB.15
    private static int[] SHORT_CUT_COUNTER = new int[MAX_SPINDLE_NUM];
    private static int[] TINY_CUT_COUNTER = new int[MAX_SPINDLE_NUM];
    private static int[] LONG_CUT_COUNTER = new int[MAX_SPINDLE_NUM];
    private static int[] N_CUT_COUNTER = new int[MAX_SPINDLE_NUM];
    private static int[] COUNTER_0X62_DB_4 = new int[MAX_SPINDLE_NUM];
    private static int[] COUNTER_0X62_DB_5 = new int[MAX_SPINDLE_NUM];
    private static int[] COUNTER_0X62_DB_6 = new int[MAX_SPINDLE_NUM];
    private static int[] COUNTER_0X62_DB_7 = new int[MAX_SPINDLE_NUM];
    private static int[] COUNTER_0X62_DB_8 = new int[MAX_SPINDLE_NUM];
    private static int[] COUNTER_0X62_DB_9 = new int[MAX_SPINDLE_NUM];
    private static int[] COUNTER_0X62_DB_10 = new int[MAX_SPINDLE_NUM];
    private static int[] COUNTER_0X62_DB_11 = new int[MAX_SPINDLE_NUM];
    private static int[] COUNTER_0X62_DB_12 = new int[MAX_SPINDLE_NUM];
    private static int[] COUNTER_0X62_DB_13 = new int[MAX_SPINDLE_NUM];
    private static int[] COUNTER_0X62_DB_14 = new int[MAX_SPINDLE_NUM];
    private static int[] COUNTER_0X62_DB_15 = new int[MAX_SPINDLE_NUM];

    private static int[][] COUNTER_0X63_DB = new int[13][MAX_SPINDLE_NUM];
    private static int[][] COUNTER_0X63_DC = new int[16][MAX_SPINDLE_NUM];
    private static int[][] COUNTER_0X63_DD = new int[5][MAX_SPINDLE_NUM];

    // frank count interval
    private WeddingTimeRecorder weddingTimeRecorder;
    private static long[] wedding_time_start = new long[MAX_SPINDLE_NUM];
    private static long[] doffing_total_time_start = new long[MAX_SPINDLE_NUM];
    private static long running_time_start = 0;
    // product data
    private static boolean[] noneFullPackageResetFlag = new boolean[MAX_SPINDLE_NUM];
    public static int succeeded_doffer_number = 0;// 小车络筒成功个数
    public static int dofferdoffing_total_number = 0;// 小车络筒个数
    public static int old_dofferdoffing_total_number;
    public static int new_dofferdoffing_total_number;
    private static float succeeded_doffer_ratio = 0.0f;
    public static int doffing_total_number = 0;// 总满筒个数、生产筒纱数。落筒总数：各单钉筒纱数的总和
    private static float succeeded_ratio = 0.0f;
    private static long running_time = 0;

    private static int[] COUNTER_0X62_DC_10 = new int[MAX_SPINDLE_NUM];// 筒纱数，针对单钉而言
    private static int[] COUNTER_0X62_DC_2 = new int[MAX_SPINDLE_NUM];
    private static int[] COUNTER_0X62_DC_3 = new int[MAX_SPINDLE_NUM];
    private static int[] COUNTER_0X62_DC_5 = new int[MAX_SPINDLE_NUM];
    private static int[] COUNTER_0X62_DC_6 = new int[MAX_SPINDLE_NUM];

    private static boolean[] COUNTER_0X62_DC_3_STATE = new boolean[MAX_SPINDLE_NUM];

    private static long[] WEDDING_TIME = new long[MAX_SPINDLE_NUM];// 络纱时间
    private static long[] DOFFING_TOTAL_TIME = new long[MAX_SPINDLE_NUM];// 落纱总时间
    private static float[] PRODUCTION_EFFICIENCY = new float[MAX_SPINDLE_NUM];//生产效率
    private static float[] MECHANICAL_EFFICIENCY = new float[MAX_SPINDLE_NUM];//机械效率

    // save to fram:key
    private static final String PRE_WEDDING_TIME = "pre_wedding_time";
    private static final String PRE_DOFFER_TOTAL_TIME = "pre_doffer_total_time";
    static final String PRE_NUMBER_COPS_CHANGE = "pre_number_cops_change";
    static final String PRE_YARN_JOINTS = "pre_yarn_joints";
    private static final String PRE_SHORT_CUT_COUNTER = "pre_short_cut_counter";
    private static final String PRE_TINY_CUT_COUNTER = "pre_tiny_cut_counter";
    private static final String PRE_LONG_CUT_COUNTER = "pre_long_cut_counter";
    private static final String PRE_N_CUT_COUNTER = "pre_n_cut_counter";
    private static final String PRE_COUNTER_0X62_DB_4 = "pre_counter_0x62_db_4";
    private static final String PRE_COUNTER_0X62_DB_5 = "pre_counter_0x62_db_5";
    private static final String PRE_COUNTER_0X62_DB_6 = "pre_counter_0x62_db_6";
    private static final String PRE_COUNTER_0X62_DB_7 = "pre_counter_0x62_db_7";
    private static final String PRE_COUNTER_0X62_DB_8 = "pre_counter_0x62_db_8";
    private static final String PRE_COUNTER_0X62_DB_9 = "pre_counter_0x62_db_9";
    private static final String PRE_COUNTER_0X62_DB_10 = "pre_counter_0x62_db_10";
    private static final String PRE_COUNTER_0X62_DB_11 = "pre_counter_0x62_db_11";
    private static final String PRE_COUNTER_0X62_DB_12 = "pre_counter_0x62_db_12";
    private static final String PRE_COUNTER_0X62_DB_13 = "pre_counter_0x62_db_13";
    private static final String PRE_COUNTER_0X62_DB_14 = "pre_counter_0x62_db_14";
    private static final String PRE_COUNTER_0X62_DB_15 = "pre_counter_0x62_db_15";
    private static final String PRE_COUNTER_0X62_DC_1 = "pre_counter_0x62_dc_1";
    private static final String PRE_COUNTER_0X62_DC_5 = "pre_counter_0x62_dc_5";
    private static final String PRE_SPLICE_CYCLES = "pre_splice_cycles";
    private static final String PRE_SPLICES_RIGHT_FIRST_TIME = "pre_splice_right_first_time";
    private static final String PRE_BUCKETL_WEIGHT = "pre_bucketl_weight";
    private static final String PRE_BUCKETL_LENGTH = "pre_bucketl_length";
    private static final String PRE_CURRENT_PULSE = "pre_current_pulse";
    private static final String PRE_SPLICE_TOTAL_TIME = "pre_splice_total_time";
    private static final String STR_SUCCEEDED_DOFFER_NUMBER = "str_succeeded_doffer_number";
    private static final String STR_DOFFERDOFFING_TOTAL_NUMBER = "str_dofferdoffing_total_number";
    private static final String STR_OLD_DOFFERDOFFING_TOTAL_NUMBER = "str_old_dofferdoffing_total_number";
    private static final String STR_DOFFING_TOTAL_NUMBER = "str_doffing_total_number";
    private static final String STR_RUNNING_TIME = "str_running_time";
    // 托举
    public static final String PACKAGE_NUMBER_ON_BELT = "package_number_on_belt";
    public static final String LIFTER_STATUS_MOVEMENT = "lifter_status_movement";
    public static final String LIFTER_STATUS_FAULT = "lifter_status_fault";
    private static Report report;

    //单锭记录
    private static final String PRE_COUNTER_0X63_DB = "pre_counter_0x63_db_";
    private static final String PRE_COUNTER_0X63_DC = "pre_counter_0x63_dc_";
    private static final String PRE_COUNTER_0X63_DD = "pre_counter_0x63_dd_";

    //报表表头key值
    public static final String TITLE = "title";

    private Box<ShiftReport> shiftBox = ObjectBox.get().boxFor(ShiftReport.class);
    private Box<StatisticRecord> statisticBox = ObjectBox.get().boxFor(StatisticRecord.class);
    private Box<CbfReport> cbfBox = ObjectBox.get().boxFor(CbfReport.class);
    private Box<GroupInfo> groupInfoBox = ObjectBox.get().boxFor(GroupInfo.class);

    private Report() {
        initData();
        weddingTimeRecorder = new WeddingTimeRecorder();
        EventBus.getDefault().register(this);
    }

    public synchronized static Report getInstance() {
        if (report == null) {
            report = new Report();
        }
        return report;
    }


    public long getShiftCount() {
        long count = shiftBox.query().build().property(ShiftReport_.start).distinct().count();
        return count + 1;
    }


    private void initData() {
        int spindleCnt = GroupMap.getInstance().getSpindleCount();
        for (int i = 0; i < spindleCnt; i++) {
            WEDDING_TIME[i] = fm.getLong(PRE_WEDDING_TIME + (i + 1), 0);
            DOFFING_TOTAL_TIME[i] = fm.getLong(PRE_DOFFER_TOTAL_TIME + (i + 1), 0);
            NUMBER_COPS_CHANGE[i] = fm.getInt(PRE_NUMBER_COPS_CHANGE + (i + 1), 0);
            YARN_JOINTS[i] = fm.getInt(PRE_YARN_JOINTS + (i + 1), 0);
            SHORT_CUT_COUNTER[i] = fm.getInt(PRE_SHORT_CUT_COUNTER + (i + 1), 0);
            TINY_CUT_COUNTER[i] = fm.getInt(PRE_TINY_CUT_COUNTER + (i + 1), 0);
            LONG_CUT_COUNTER[i] = fm.getInt(PRE_LONG_CUT_COUNTER + (i + 1), 0);
            N_CUT_COUNTER[i] = fm.getInt(PRE_N_CUT_COUNTER + (i + 1), 0);
            COUNTER_0X62_DB_4[i] = fm.getInt(PRE_COUNTER_0X62_DB_4 + (i + 1), 0);
            COUNTER_0X62_DB_5[i] = fm.getInt(PRE_COUNTER_0X62_DB_5 + (i + 1), 0);
            COUNTER_0X62_DB_6[i] = fm.getInt(PRE_COUNTER_0X62_DB_6 + (i + 1), 0);
            COUNTER_0X62_DB_7[i] = fm.getInt(PRE_COUNTER_0X62_DB_7 + (i + 1), 0);
            COUNTER_0X62_DB_8[i] = fm.getInt(PRE_COUNTER_0X62_DB_8 + (i + 1), 0);
            COUNTER_0X62_DB_9[i] = fm.getInt(PRE_COUNTER_0X62_DB_9 + (i + 1), 0);
            COUNTER_0X62_DB_10[i] = fm.getInt(PRE_COUNTER_0X62_DB_10 + (i + 1), 0);
            COUNTER_0X62_DB_11[i] = fm.getInt(PRE_COUNTER_0X62_DB_11 + (i + 1), 0);
            COUNTER_0X62_DB_12[i] = fm.getInt(PRE_COUNTER_0X62_DB_12 + (i + 1), 0);
            COUNTER_0X62_DB_13[i] = fm.getInt(PRE_COUNTER_0X62_DB_13 + (i + 1), 0);
            COUNTER_0X62_DB_14[i] = fm.getInt(PRE_COUNTER_0X62_DB_14 + (i + 1), 0);
            COUNTER_0X62_DB_15[i] = fm.getInt(PRE_COUNTER_0X62_DB_15 + (i + 1), 0);
            COUNTER_0X62_DC_10[i] = fm.getInt(PRE_COUNTER_0X62_DC_1 + (i + 1), 0);
            COUNTER_0X62_DC_5[i] = fm.getInt(PRE_COUNTER_0X62_DC_5 + (i + 1), 0);
            SPLICE_CYCLES[i] = fm.getInt(PRE_SPLICE_CYCLES + (i + 1), 0);
            SPLICES_RIGHT_FIRST_TIME[i] = fm.getInt(PRE_SPLICES_RIGHT_FIRST_TIME + (i + 1), 0);
            BICKETL_WEIGHT[i] = fm.getFloat(PRE_BUCKETL_WEIGHT + (i + 1), 0);
            BICKETL_LENGTH[i] = fm.getInt(PRE_BUCKETL_LENGTH + (i + 1), 0);
            currentPulse[i] = fm.getInt(PRE_CURRENT_PULSE + (i + 1), 0);
            SPLICE_TOTAL_TIME[i] = fm.getLong(PRE_SPLICE_TOTAL_TIME + (i + 1), 0);
            calcEfficiency(i);

            for (int offset = 0; offset < 13; ++offset) {
                COUNTER_0X63_DB[offset][i] = fm.getInt(PRE_COUNTER_0X63_DB + offset + (i + 1), 0);
            }

            for (int offset = 0; offset < 16; ++offset) {
                COUNTER_0X63_DC[offset][i] = fm.getInt(PRE_COUNTER_0X63_DC + offset + (i + 1), 0);
            }

            for (int offset = 0; offset < 5; ++offset) {
                COUNTER_0X63_DD[offset][i] = fm.getInt(PRE_COUNTER_0X63_DD + offset + (i + 1), 0);
            }

        }
        succeeded_doffer_number = fm.getInt(STR_SUCCEEDED_DOFFER_NUMBER, 0);
        dofferdoffing_total_number = fm.getInt(STR_DOFFERDOFFING_TOTAL_NUMBER, 0);
        old_dofferdoffing_total_number = fm.getInt(STR_OLD_DOFFERDOFFING_TOTAL_NUMBER, 0);
        new_dofferdoffing_total_number = old_dofferdoffing_total_number;
        doffing_total_number = fm.getInt(STR_DOFFING_TOTAL_NUMBER, 0);
        running_time = fm.getLong(STR_RUNNING_TIME, 0);
    }

    public String subSecToTime(long s) {
        StringBuilder sb = new StringBuilder();
        int hour = (int) s / 3600;
        int min = (int) (s % 3600) / 60;
        int sec = (int) s % 3600 % 60;

        if (hour < 10) {
            sb.append("0" + hour);
        } else {
            sb.append(hour);
        }
        sb.append(":");
        if (min < 10) {
            sb.append("0" + min);
        } else {
            sb.append(min);
        }
        sb.append(":");
        if (sec < 10) {
            sb.append("0" + sec);
        } else {
            sb.append(sec);
        }
        return sb.toString();
    }

    /* 络纱时间 */
    private interface BM_0x62_DC_INDEX {
        int BM_0X62_DC_0 = 0x01;
        int BM_0X62_DC_1 = 0x02;
        int BM_0X62_DC_2 = 0x04;
        int BM_0X62_DC_3 = 0x08;
        int BM_0X62_DC_5 = 0x20;
        int BM_0X62_DC_6 = 0x40;
        int BM_0X62_DC_10 = 0x400;
        int BM_0X62_DC_11 = 0x800;
    }

    private interface SpindleStateType {
        int stateZeroToOne = 0;
        int stateOneToOne = 1;
        int stateOneToZero = 2;
    }

    private static boolean compareState(int oldData, int newData, int offset, int type) {
        switch (type) {
            case SpindleStateType.stateZeroToOne:
                return ((newData & offset) == offset) && ((oldData & offset) == 0);

            case SpindleStateType.stateOneToOne:
                return ((newData & offset) == offset) && ((oldData & offset) == offset);

            case SpindleStateType.stateOneToZero:
                return ((newData & offset) == 0) && ((oldData & offset) == offset);

        }
        return false;
    }

    public void parse62DC(int spindleSeq, int oldData, int newData) {

        int spindle_idx = spindleSeq - 1;
        // 单锭状态信号
        if (compareState(oldData, newData, BM_0x62_DC_INDEX.BM_0X62_DC_0, SpindleStateType.stateZeroToOne)) {
            weddingTimeRecorder.start(spindle_idx);
        } else if (compareState(oldData, newData, BM_0x62_DC_INDEX.BM_0X62_DC_0, SpindleStateType.stateOneToOne)) {
        } else if (compareState(oldData, newData, BM_0x62_DC_INDEX.BM_0X62_DC_0, SpindleStateType.stateOneToZero)) {
            weddingTimeRecorder.stop(spindle_idx);
        }

        // 满筒请求信号
        if (((newData & BM_0x62_DC_INDEX.BM_0X62_DC_1) == BM_0x62_DC_INDEX.BM_0X62_DC_1)
                && ((oldData & BM_0x62_DC_INDEX.BM_0X62_DC_1) == 0)) {
            doffing_total_time_start[spindle_idx] = System.currentTimeMillis();
        } else if (((newData & BM_0x62_DC_INDEX.BM_0X62_DC_1) == BM_0x62_DC_INDEX.BM_0X62_DC_1)
                && ((oldData & BM_0x62_DC_INDEX.BM_0X62_DC_1) == BM_0x62_DC_INDEX.BM_0X62_DC_1)) {
            if (doffing_total_time_start[spindle_idx] != 0) {
                long val = System.currentTimeMillis() - doffing_total_time_start[spindle_idx];
                if (val > 0 && PLCData.getInstance().getHoldingRegister(1, 253) != 0)
                    DOFFING_TOTAL_TIME[spindle_idx] += val;
            }
            doffing_total_time_start[spindle_idx] = System.currentTimeMillis();
        } else if (((newData & BM_0x62_DC_INDEX.BM_0X62_DC_1) == 0)
                && ((oldData & BM_0x62_DC_INDEX.BM_0X62_DC_1) == BM_0x62_DC_INDEX.BM_0X62_DC_1)) {// 1变0
            if (doffing_total_time_start[spindle_idx] != 0) {
                long val = System.currentTimeMillis() - doffing_total_time_start[spindle_idx];
                if (val > 0 && PLCData.getInstance().getHoldingRegister(1, 253) != 0)
                    DOFFING_TOTAL_TIME[spindle_idx] += val;
            }
            doffing_total_time_start[spindle_idx] = 0;
        }

        if (((newData & BM_0x62_DC_INDEX.BM_0X62_DC_10) == BM_0x62_DC_INDEX.BM_0X62_DC_10)
                && ((oldData & BM_0x62_DC_INDEX.BM_0X62_DC_10) == 0)) {// 0变1
            COUNTER_0X62_DC_10[spindle_idx]++;
            doffing_total_number++;
            dofferNumbers();
        }

        // 未满筒复位信号
        if (((newData & BM_0x62_DC_INDEX.BM_0X62_DC_2) == BM_0x62_DC_INDEX.BM_0X62_DC_2)
                && ((oldData & BM_0x62_DC_INDEX.BM_0X62_DC_2) == 0)) {
            noneFullPackageResetFlag[spindle_idx] = true;
            COUNTER_0X62_DC_2[spindle_idx]++;
        }

        // 按停车按钮停车
        if (((newData & BM_0x62_DC_INDEX.BM_0X62_DC_3) == BM_0x62_DC_INDEX.BM_0X62_DC_3)
                && ((oldData & BM_0x62_DC_INDEX.BM_0X62_DC_3) == 0)) {
            COUNTER_0X62_DC_3[spindle_idx]++;
            COUNTER_0X62_DC_3_STATE[spindle_idx] = true;
        } else if (((newData & BM_0x62_DC_INDEX.BM_0X62_DC_3) == 0)
                && ((oldData & BM_0x62_DC_INDEX.BM_0X62_DC_3) == BM_0x62_DC_INDEX.BM_0X62_DC_3)) {
            COUNTER_0X62_DC_3_STATE[spindle_idx] = false;
        }

        // （满筒清零换筒）单锭启动成功
        if (((newData & BM_0x62_DC_INDEX.BM_0X62_DC_5) == BM_0x62_DC_INDEX.BM_0X62_DC_5)
                && ((oldData & BM_0x62_DC_INDEX.BM_0X62_DC_5) == 0)) {
            COUNTER_0X62_DC_5[spindle_idx]++;
            succeeded_doffer_number++;
            dofferNumbers();
        }

        // 单锭完全停车
        if (((newData & BM_0x62_DC_INDEX.BM_0X62_DC_6) == BM_0x62_DC_INDEX.BM_0X62_DC_6)
                && ((oldData & BM_0x62_DC_INDEX.BM_0X62_DC_6) == 0)) {
            COUNTER_0X62_DC_6[spindle_idx]++;

        }
        try {
            fm.putLong(PRE_DOFFER_TOTAL_TIME + spindleSeq, DOFFING_TOTAL_TIME[spindle_idx]);
            fm.putInt(PRE_COUNTER_0X62_DC_1 + spindleSeq, COUNTER_0X62_DC_10[spindle_idx]);
            fm.putInt(PRE_COUNTER_0X62_DC_5 + spindleSeq, COUNTER_0X62_DC_5[spindle_idx]);
            fm.putInt(STR_SUCCEEDED_DOFFER_NUMBER, succeeded_doffer_number);
            fm.putInt(STR_DOFFING_TOTAL_NUMBER, doffing_total_number);
            fm.putInt(PACKAGE_NUMBER_ON_BELT, dofferdoffing_total_number);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void parse63DB(int spindleSeq, int oldData, int newData) {
        int spindle_idx = spindleSeq - 1;

        for (int offset = 0; offset < 13; ++offset) {
            if (compareState(oldData, newData, 1 << offset, SpindleStateType.stateZeroToOne)) {
                ++COUNTER_0X63_DB[offset][spindle_idx];
                try {
                    fm.putInt(PRE_COUNTER_0X63_DB + offset + spindleSeq, COUNTER_0X63_DB[offset][spindle_idx]);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void parse63DC(int spindleSeq, int oldData, int newData) {
        int spindle_idx = spindleSeq - 1;

        for (int offset = 0; offset < 16; ++offset) {
            if (compareState(oldData, newData, 1 << offset, SpindleStateType.stateZeroToOne)) {
                ++COUNTER_0X63_DC[offset][spindle_idx];
                try {
                    fm.putInt(PRE_COUNTER_0X63_DC + offset + spindleSeq, COUNTER_0X63_DC[offset][spindle_idx]);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void parse63DD(int spindleSeq, int oldData, int newData) {
        int spindle_idx = spindleSeq - 1;

        for (int offset = 0; offset < 5; ++offset) {
            if (compareState(oldData, newData, 1 << offset, SpindleStateType.stateZeroToOne)) {
                ++COUNTER_0X63_DD[offset][spindle_idx];
                try {
                    fm.putInt(PRE_COUNTER_0X63_DD + offset + spindleSeq, COUNTER_0X63_DD[offset][spindle_idx]);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public int getCountSum(int[] counter) {
        int sum = 0;
        for (int i = 0; i < counter.length; ++i) {
            sum += counter[i];
        }
        return sum;
    }

    public int getCountSum(int[] counter, int group) {
        int sum = 0;
        List<Integer> list = GroupMap.getInstance().getSpindleList(group);
        for (Integer i : list) {
            sum += counter[i - 1];
        }
        return sum;
    }

    public int[][] get0X63DBCounter() {
        return COUNTER_0X63_DB;
    }

    public int[][] get0X63DCCounter() {
        return COUNTER_0X63_DC;
    }

    public int[][] get0X63DDCounter() {
        return COUNTER_0X63_DD;
    }

    public void dofferNumbers() {

        int divisor = 0;
        int dividend = 0;
        float ratio = 0.0f;

        ratio = 0.0f;
        divisor = succeeded_doffer_number;
        dividend = dofferdoffing_total_number;
        if (dividend != 0)
            ratio = (divisor) * 100.0f / (dividend);

        if ((ratio > 100.0f) || (ratio < 0.0f))
            ratio = 100.0f;

        succeeded_doffer_ratio = reFloat(ratio);

        ratio = 0.0f;
        divisor = succeeded_doffer_number;
        dividend = doffing_total_number;// 满筒个数
        if (dividend != 0)
            ratio = (divisor) * 100.0f / (dividend);

        if ((ratio > 100.0f) || (ratio < 0.0f))
            ratio = 100.0f;

        succeeded_ratio = reFloat(ratio);
    }

    // 小车落筒个数
    public String getDofferDoffingTotalNumber() {
        return String.valueOf(dofferdoffing_total_number);
    }

    public String getSucceededDofferNumber() {
        return String.valueOf(succeeded_doffer_number);
    }

    public String getDoffingTotalNumber() {
        return String.valueOf(doffing_total_number);
    }

    // 总落筒成功百分率
    public String getSucceededRatio() {
        dofferNumbers();
        return String.valueOf(succeeded_ratio);
    }

    // 小车落筒成功百分率
    public String getSucceededDofferRatio() {
        dofferNumbers();
        return String.valueOf(succeeded_doffer_ratio);
    }

    /**
     * // 小数点后面两位, String.format("%1$.2f", 123.456));
     */
    public float reFloat(float value) {
        return Float.parseFloat(round(String.valueOf(value), 2));
    }

    /**
     * 提供精确的小数位四舍五入处理,舍入模式采用ROUND_HALF_UP
     *
     * @param value 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果，以字符串格式返回
     */
    public static String round(String value, int scale) {
        if (scale < 0)
            scale = 0;
        BigDecimal bd = new BigDecimal(value);
        bd = bd.setScale(scale, BigDecimal.ROUND_HALF_UP);
        return bd.toString();
    }

    // 运行时间
    public long getRunningTime() {
        return running_time;
    }

    // 络纱时间
    public long getWeddingTime(int spindle) {
        int spindleIndex = spindle - 1;
        return WEDDING_TIME[spindleIndex];
    }

    // 各个单钉生产的筒纱数 落筒总数（落纱总数）
    public int getDofingSpindleAmount(int spindle) {
        int spindleIndex = spindle - 1;
        return COUNTER_0X62_DC_10[spindleIndex];
    }

    // 落筒总时间
    public long get_doffing_total_time(int spindle) {
        int spindleIndex = spindle - 1;
        return DOFFING_TOTAL_TIME[spindleIndex];
    }

    public long getSpindleStopTime(int spindleId) {
        long start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
        long end = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftEndTime());
        Box<RedLightRecord> boxRed = ObjectBox.get().boxFor(RedLightRecord.class);
        Box<ProcessRecord> boxProcess = ObjectBox.get().boxFor(ProcessRecord.class);
        Box<FaultRecord> boxFault = ObjectBox.get().boxFor(FaultRecord.class);
        long redTime = boxRed.query().equal(RedLightRecord_.spindleId, spindleId)
                .between(RedLightRecord_.start, start, end).build().property(RedLightRecord_.duration).sum();
        long processTime = boxProcess.query().equal(ProcessRecord_.spindleId, spindleId)
                .between(ProcessRecord_.start, start, end).build().property(ProcessRecord_.duration).sum();
        long faultTime = boxFault.query().equal(FaultRecord_.spindleId, spindleId)
                .between(FaultRecord_.start, start, end).build().property(FaultRecord_.duration).sum();
        return redTime + processTime + faultTime;
    }

    public void calcEfficiency(int spindleId) {
        long spindleStopTime = getSpindleStopTime(spindleId + 1);
        long windingTime = WEDDING_TIME[spindleId];
        long spliceTime = SPLICE_TOTAL_TIME[spindleId];
        long totalTime = windingTime + spliceTime + spindleStopTime;
        // 单锭生产效率
        if (totalTime != 0) {
            PRODUCTION_EFFICIENCY[spindleId] = (windingTime * 100.0f) / totalTime;
        }
        // 单锭机械效率
        if ((WEDDING_TIME[spindleId] + SPLICE_TOTAL_TIME[spindleId]) != 0) {
            MECHANICAL_EFFICIENCY[spindleId] = WEDDING_TIME[spindleId] * 100.0f / (WEDDING_TIME[spindleId] + SPLICE_TOTAL_TIME[spindleId]);
        }

    }

    public float getSpindleProductionEfficiency(int spindle) {
        return PRODUCTION_EFFICIENCY[spindle - 1];
    }

    public float getTotalProductionEfficiency() {

        float result = 0.0f;
        String str_total_spindles_number = MachineParameterSharedPreference.getInstance().getValue(0x29, 0x01);
        int total_spindles_number = 72;
        if (str_total_spindles_number != null) {
            total_spindles_number = Integer.parseInt(str_total_spindles_number);
        }
        for (int i = 1; i <= total_spindles_number; i++) {
            result += getSpindleProductionEfficiency(i);
        }
        return result / total_spindles_number;
    }

    public float getSpindleMechanicalEfficiency(int spindle) {
        return MECHANICAL_EFFICIENCY[spindle - 1];
    }

    @Subscribe
    public void calcRunningTime(PLCData.HoldingRegister register) {
        if (register.addr == 253) {
            if (register.oldValue == 0 && register.value != 0) {
                weddingTimeRecorder.machineStart();
            } else if (register.value == 0) {
                weddingTimeRecorder.machineStop();
            }
        }

    }

    // 小车成功落筒个数
    public int getSucceededSpindleDofferNumber(int spindle) {
        int spindleIndex = spindle - 1;
        return COUNTER_0X62_DC_5[spindleIndex];
    }

    public void parse61Cmd(int spindleId, int db, int dc, int dd) {
        int spindle_index = spindleId - 1;
        YARN_JOINTS[spindle_index]++;
        SPLICE_CYCLES[spindle_index] += dc;
        NUMBER_COPS_CHANGE[spindle_index] += dd;
        SPLICE_TOTAL_TIME[spindle_index] += db;

        try {
            fm.putInt(PRE_NUMBER_COPS_CHANGE + spindleId, NUMBER_COPS_CHANGE[spindle_index]);
            fm.putInt(PRE_YARN_JOINTS + spindleId, YARN_JOINTS[spindle_index]);
            fm.putInt(PRE_SPLICE_CYCLES + spindleId, SPLICE_CYCLES[spindle_index]);
            fm.putLong(PRE_SPLICE_TOTAL_TIME + spindleId, SPLICE_TOTAL_TIME[spindle_index]);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void parse64Cmd(int spindleId, int dc) {
        if (dc > 500) {
            int spindle_index = spindleId - 1;
            TUBE_LENGTH[spindle_index] = dc;
        }
    }

    public void parse65Cmd(int spindleId, int db, int dc, int dd) {
        int spindle_index = spindleId - 1;
        SPLICES_RIGHT_FIRST_TIME[spindle_index] += db;
        try {
            fm.putInt(PRE_SPLICES_RIGHT_FIRST_TIME + spindleId, SPLICES_RIGHT_FIRST_TIME[spindle_index]);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 管纱长度
    public int getTubeLength(int spindle) {
        int spindleIndex = spindle - 1;
        return TUBE_LENGTH[spindleIndex];
    }

    // 接头数
    public int getYarnJoints(int spindle) {
        int spindleIndex = spindle - 1;
        return YARN_JOINTS[spindleIndex];
    }

    public float getYarnJointsDiv10(int spindleId) {
        float yarnJointsDiv10 = 0.0f;
        if (BICKETL_LENGTH[spindleId - 1] > 0) {
            yarnJointsDiv10 = YARN_JOINTS[spindleId - 1] * (10 * 1000) / BICKETL_LENGTH[spindleId - 1];
        }
        return yarnJointsDiv10;
    }

    public float getYarnJointsDivPackage(int spindleId) {

        float yarnJointsDivPackage = 0.0f;
        int doffingAmount = getDofingSpindleAmount(spindleId);
        int yarnJoints = getYarnJoints(spindleId);
        if (doffingAmount < 1) {
            yarnJointsDivPackage = yarnJoints;
        } else {
            yarnJointsDivPackage = yarnJoints / doffingAmount;
        }

        return yarnJointsDivPackage;
    }

    public float getNumberCutOfFaultsDiv10(int spindleId) {

        float numberCutOfFaultsDiv10 = 0.0f;
        if (BICKETL_LENGTH[spindleId - 1] > 0) {
            numberCutOfFaultsDiv10 = getNumberCutOfFaults(spindleId) * (100 * 1000) / BICKETL_LENGTH[spindleId - 1];
        }
        return numberCutOfFaultsDiv10;

    }

    public float getnumberCutOfFaultsDivPackage(int spindleId) {

        float numberCutOfFaultsDivPackage = 0.0f;
        int doffingAmount = getDofingSpindleAmount(spindleId);
        int numberCutOfFaults = getNumberCutOfFaults(spindleId);
        if (doffingAmount < 1) {
            numberCutOfFaultsDivPackage = numberCutOfFaults;
        } else {
            numberCutOfFaultsDivPackage = numberCutOfFaults * 1f / doffingAmount;
        }

        return numberCutOfFaultsDivPackage;
    }

    public float getnumberCutOfFaultsDivCop(int spindleId) {

        float numberCutOfFaultsDivCop = 0.0f;
        int numberCutOfFaults = getNumberCutOfFaults(spindleId);
        int numberCopsChange = getNumberCopsChange(spindleId);

        if (numberCopsChange < 1) {
            numberCutOfFaultsDivCop = numberCutOfFaults;
        } else {
            numberCutOfFaultsDivCop = numberCutOfFaults * 1f / numberCopsChange;
        }
        return numberCutOfFaultsDivCop;
    }

    // 接头总时间
    public long getSpliceTotalTime(int spindle) {
        int spindleIndex = spindle - 1;
        return SPLICE_TOTAL_TIME[spindleIndex];
    }

    // 更换管纱次数
    public int getNumberCopsChange(int spindle) {
        int spindleIndex = spindle - 1;
        return NUMBER_COPS_CHANGE[spindleIndex];
    }

    // 捻接次数
    public int getSpliceCycles(int spindle) {
        int spindleIndex = spindle - 1;
        return SPLICE_CYCLES[spindleIndex];
    }

    // 一次成功捻接次数
    public int getSplicesRightFirstTime(int spindle) {
        int spindleIndex = spindle - 1;
        return SPLICES_RIGHT_FIRST_TIME[spindleIndex];
    }

    private interface BM_0x62_DB_INDEX {
        static final int SHORT_CUT = 0x01; // DB0 TEXTILE
        static final int TINY_CUT = 0x02; // DB1 TEXTILE
        static final int LONG_CUT = 0x04; // DB2 TEXTILE
        static final int N_CUT = 0x08; // DB3 TEXTILE
        static final int BM_0X62_DB_4 = 0x10; // DB4 TEXTILE
        static final int BM_0X62_DB_5 = 0x20; // DB5 TEXTILE
        static final int BM_0X62_DB_6 = 0x40; // DB6 TEXTILE
        static final int BM_0X62_DB_7 = 0x80; // DB7 TEXTILE
        static final int BM_0X62_DB_8 = 0x100; // DB8 TEXTILE
        static final int BM_0X62_DB_9 = 0x200; // DB9 TEXTILE
        static final int BM_0X62_DB_10 = 0x400; // DB10 TEXTILE
        static final int BM_0X62_DB_11 = 0x800; // DB11 TEXTILE
        static final int BM_0X62_DB_12 = 0x1000; // DB13 TEXTILE
        static final int BM_0X62_DB_13 = 0x2000; // DB13 TEXTILE
        static final int BM_0X62_DB_14 = 0x4000; // DB14 TEXTILE
        static final int BM_0X62_DB_15 = 0x8000; // DB15 TEXTILE
    }

    public void parse62DB(int spindleId, int oldData, int newData) {
        int spindle_idx = spindleId - 1;
        if (((newData & BM_0x62_DB_INDEX.SHORT_CUT) == BM_0x62_DB_INDEX.SHORT_CUT)
                && ((oldData & BM_0x62_DB_INDEX.SHORT_CUT) == 0)) {
            SHORT_CUT_COUNTER[spindle_idx]++;
        }
        if (((newData & BM_0x62_DB_INDEX.TINY_CUT) == BM_0x62_DB_INDEX.TINY_CUT)
                && ((oldData & BM_0x62_DB_INDEX.TINY_CUT) == 0)) {
            TINY_CUT_COUNTER[spindle_idx]++;
        }
        if (((newData & BM_0x62_DB_INDEX.LONG_CUT) == BM_0x62_DB_INDEX.LONG_CUT)
                && ((oldData & BM_0x62_DB_INDEX.LONG_CUT) == 0)) {
            LONG_CUT_COUNTER[spindle_idx]++;
        }
        if (((newData & BM_0x62_DB_INDEX.N_CUT) == BM_0x62_DB_INDEX.N_CUT)
                && ((oldData & BM_0x62_DB_INDEX.N_CUT) == 0)) {
            N_CUT_COUNTER[spindle_idx]++;
        }
        if (((newData & BM_0x62_DB_INDEX.BM_0X62_DB_4) == BM_0x62_DB_INDEX.BM_0X62_DB_4)
                && ((oldData & BM_0x62_DB_INDEX.BM_0X62_DB_4) == 0)) {
            COUNTER_0X62_DB_4[spindle_idx]++;
        }
        if (((newData & BM_0x62_DB_INDEX.BM_0X62_DB_5) == BM_0x62_DB_INDEX.BM_0X62_DB_5)
                && ((oldData & BM_0x62_DB_INDEX.BM_0X62_DB_5) == 0)) {
            COUNTER_0X62_DB_5[spindle_idx]++;
        }
        if (((newData & BM_0x62_DB_INDEX.BM_0X62_DB_6) == BM_0x62_DB_INDEX.BM_0X62_DB_6)
                && ((oldData & BM_0x62_DB_INDEX.BM_0X62_DB_6) == 0)) {
            COUNTER_0X62_DB_6[spindle_idx]++;
        }
        if (((newData & BM_0x62_DB_INDEX.BM_0X62_DB_7) == BM_0x62_DB_INDEX.BM_0X62_DB_7)
                && ((oldData & BM_0x62_DB_INDEX.BM_0X62_DB_7) == 0)) {
            COUNTER_0X62_DB_7[spindle_idx]++;
        }
        if (((newData & BM_0x62_DB_INDEX.BM_0X62_DB_8) == BM_0x62_DB_INDEX.BM_0X62_DB_8)
                && ((oldData & BM_0x62_DB_INDEX.BM_0X62_DB_8) == 0)) {
            COUNTER_0X62_DB_8[spindle_idx]++;
        }
        if (((newData & BM_0x62_DB_INDEX.BM_0X62_DB_9) == BM_0x62_DB_INDEX.BM_0X62_DB_9)
                && ((oldData & BM_0x62_DB_INDEX.BM_0X62_DB_9) == 0)) {
            COUNTER_0X62_DB_9[spindle_idx]++;
        }
        if (((newData & BM_0x62_DB_INDEX.BM_0X62_DB_10) == BM_0x62_DB_INDEX.BM_0X62_DB_10)
                && ((oldData & BM_0x62_DB_INDEX.BM_0X62_DB_10) == 0)) {
            COUNTER_0X62_DB_10[spindle_idx]++;
        }
        if (((newData & BM_0x62_DB_INDEX.BM_0X62_DB_11) == BM_0x62_DB_INDEX.BM_0X62_DB_11)
                && ((oldData & BM_0x62_DB_INDEX.BM_0X62_DB_11) == 0)) {
            COUNTER_0X62_DB_11[spindle_idx]++;
        }
        if (((newData & BM_0x62_DB_INDEX.BM_0X62_DB_12) == BM_0x62_DB_INDEX.BM_0X62_DB_12)
                && ((oldData & BM_0x62_DB_INDEX.BM_0X62_DB_12) == 0)) {
            COUNTER_0X62_DB_12[spindle_idx]++;
        }
        if (((newData & BM_0x62_DB_INDEX.BM_0X62_DB_13) == BM_0x62_DB_INDEX.BM_0X62_DB_13)
                && ((oldData & BM_0x62_DB_INDEX.BM_0X62_DB_13) == 0)) {
            COUNTER_0X62_DB_13[spindle_idx]++;
        }
        if (((newData & BM_0x62_DB_INDEX.BM_0X62_DB_14) == BM_0x62_DB_INDEX.BM_0X62_DB_14)
                && ((oldData & BM_0x62_DB_INDEX.BM_0X62_DB_14) == 0)) {
            COUNTER_0X62_DB_14[spindle_idx]++;
        }
        if (((newData & BM_0x62_DB_INDEX.BM_0X62_DB_15) == BM_0x62_DB_INDEX.BM_0X62_DB_15)
                && ((oldData & BM_0x62_DB_INDEX.BM_0X62_DB_15) == 0)) {
            COUNTER_0X62_DB_15[spindle_idx]++;
        }
        try {
            fm.putInt(PRE_SHORT_CUT_COUNTER + spindleId, SHORT_CUT_COUNTER[spindle_idx]);
            fm.putInt(PRE_TINY_CUT_COUNTER + spindleId, TINY_CUT_COUNTER[spindle_idx]);
            fm.putInt(PRE_LONG_CUT_COUNTER + spindleId, LONG_CUT_COUNTER[spindle_idx]);
            fm.putInt(PRE_N_CUT_COUNTER + spindleId, N_CUT_COUNTER[spindle_idx]);
            fm.putInt(PRE_COUNTER_0X62_DB_4 + spindleId, COUNTER_0X62_DB_4[spindle_idx]);
            fm.putInt(PRE_COUNTER_0X62_DB_5 + spindleId, COUNTER_0X62_DB_5[spindle_idx]);
            fm.putInt(PRE_COUNTER_0X62_DB_6 + spindleId, COUNTER_0X62_DB_6[spindle_idx]);
            fm.putInt(PRE_COUNTER_0X62_DB_7 + spindleId, COUNTER_0X62_DB_7[spindle_idx]);
            fm.putInt(PRE_COUNTER_0X62_DB_8 + spindleId, COUNTER_0X62_DB_8[spindle_idx]);
            fm.putInt(PRE_COUNTER_0X62_DB_9 + spindleId, COUNTER_0X62_DB_9[spindle_idx]);
            fm.putInt(PRE_COUNTER_0X62_DB_10 + spindleId, COUNTER_0X62_DB_10[spindle_idx]);
            fm.putInt(PRE_COUNTER_0X62_DB_11 + spindleId, COUNTER_0X62_DB_11[spindle_idx]);
            fm.putInt(PRE_COUNTER_0X62_DB_12 + spindleId, COUNTER_0X62_DB_12[spindle_idx]);
            fm.putInt(PRE_COUNTER_0X62_DB_13 + spindleId, COUNTER_0X62_DB_13[spindle_idx]);
            fm.putInt(PRE_COUNTER_0X62_DB_14 + spindleId, COUNTER_0X62_DB_14[spindle_idx]);
            fm.putInt(PRE_COUNTER_0X62_DB_15 + spindleId, COUNTER_0X62_DB_15[spindle_idx]);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 切疵次数
    public int getNumberCutOfFaults(int spindle) {
        int spindleIndex = spindle - 1;
        return SHORT_CUT_COUNTER[spindleIndex] + TINY_CUT_COUNTER[spindleIndex] + LONG_CUT_COUNTER[spindleIndex]
                + N_CUT_COUNTER[spindleIndex] + COUNTER_0X62_DB_4[spindleIndex] + COUNTER_0X62_DB_5[spindleIndex]
                + COUNTER_0X62_DB_6[spindleIndex] + COUNTER_0X62_DB_7[spindleIndex] + COUNTER_0X62_DB_8[spindleIndex]
                + COUNTER_0X62_DB_9[spindleIndex] + COUNTER_0X62_DB_10[spindleIndex] + COUNTER_0X62_DB_11[spindleIndex]
                + COUNTER_0X62_DB_12[spindleIndex] + COUNTER_0X62_DB_13[spindleIndex] + COUNTER_0X62_DB_14[spindleIndex]
                + COUNTER_0X62_DB_15[spindleIndex];
    }

    // 筒纱长度
    private static int[] currentPulse = new int[MAX_SPINDLE_NUM];
    /**
     * PULSE_TO_LENGTH_FACTOR = (0.295 * 8191)/24
     */
    private static int[] BICKETL_LENGTH = new int[MAX_SPINDLE_NUM];// 单钉长度：筒纱长度累计值
    private static float[] BICKETL_WEIGHT = new float[MAX_SPINDLE_NUM];// 单钉产量：筒纱重量累计值


    public void parse60Cmd(int spindleId, int db, int dc) {
        int spindle_index = spindleId - 1;
        int deltaPulse = db - currentPulse[spindle_index];
        if (deltaPulse > 0 && deltaPulse < 10) {
            int deltaLength = UnitUtils.pulse2Length(deltaPulse, spindleId);
            BICKETL_LENGTH[spindle_index] += deltaLength;
            BICKETL_WEIGHT[spindle_index] += UnitUtils.length2Weight(deltaLength, spindleId);
        }
        currentPulse[spindle_index] = db;

        try {
            fm.putInt(PRE_BUCKETL_LENGTH + spindleId, BICKETL_LENGTH[spindle_index]);
            fm.putFloat(PRE_BUCKETL_WEIGHT + spindleId, BICKETL_WEIGHT[spindle_index]);
            fm.putInt(PRE_CURRENT_PULSE + spindleId, currentPulse[spindle_index]);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 当前筒纱长度
    public int getCurrentPulse(int spindleId) {
        return currentPulse[spindleId - 1];
    }

    // 单钉产量
    public float getBucketWeight(int spindleId) {
        return BICKETL_WEIGHT[spindleId - 1];
    }

    public int getBucketLength(int spindleId) {
        return BICKETL_LENGTH[spindleId - 1];
    }

    // 单钉当前班总产量
    public float getTotalBucketWeight() {
        String str_total_spindles_number = MachineParameterSharedPreference.getInstance().getValue(0x29, 0x01);
        int total_spindles_number = 72;
        if (str_total_spindles_number != null) {
            total_spindles_number = Integer.parseInt(str_total_spindles_number);
        }
        float result = 0.0f;
        for (int i = 0; i < total_spindles_number; i++) {
            result += BICKETL_WEIGHT[i];
        }
        return result;
    }

    // 当前单锭筒纱重量
    public float getTotalBucketWeightWinding() {
        String str_total_spindles_number = MachineParameterSharedPreference.getInstance().getValue(0x29, 0x01);
        int total_spindles_number = 72;
        if (str_total_spindles_number != null) {
            total_spindles_number = Integer.parseInt(str_total_spindles_number);
        }
        float result = 0.0f;
        for (int i = 1; i <= total_spindles_number; i++) {
            int length = UnitUtils.pulse2Length(currentPulse[i - 1], i);
            result += UnitUtils.length2Weight(length, i);
        }
        return UnitUtils.getUIWeightFromWeight(result * 1000);
    }


    public void clearGroupReportManual(int groupNo) {
        Group group = GroupMap.getInstance().getGroupList().get(groupNo - 1);
        int startIndex = group.getStartSpindle() - 1;
        int endIndex = group.getEndSpindle() - 1;

        for (int index = startIndex; index <= endIndex; ++index) {
            WEDDING_TIME[index] = 0;
            DOFFING_TOTAL_TIME[index] = 0;
            PRODUCTION_EFFICIENCY[index] = 0;
            MECHANICAL_EFFICIENCY[index] = 0;
            NUMBER_COPS_CHANGE[index] = 0;
            YARN_JOINTS[index] = 0;
            SHORT_CUT_COUNTER[index] = 0;
            TINY_CUT_COUNTER[index] = 0;
            LONG_CUT_COUNTER[index] = 0;
            N_CUT_COUNTER[index] = 0;
            COUNTER_0X62_DB_4[index] = 0;
            COUNTER_0X62_DB_5[index] = 0;
            COUNTER_0X62_DB_6[index] = 0;
            COUNTER_0X62_DB_7[index] = 0;
            COUNTER_0X62_DB_8[index] = 0;
            COUNTER_0X62_DB_9[index] = 0;
            COUNTER_0X62_DB_10[index] = 0;
            COUNTER_0X62_DB_11[index] = 0;
            COUNTER_0X62_DB_12[index] = 0;
            COUNTER_0X62_DB_13[index] = 0;
            COUNTER_0X62_DB_14[index] = 0;
            COUNTER_0X62_DB_15[index] = 0;
            COUNTER_0X62_DC_10[index] = 0;
            COUNTER_0X62_DC_5[index] = 0;
            SPLICE_CYCLES[index] = 0;
            SPLICES_RIGHT_FIRST_TIME[index] = 0;
            BICKETL_LENGTH[index] = 0;
            BICKETL_WEIGHT[index] = 0;
            SPLICE_TOTAL_TIME[index] = 0;

            for (int offset = 0; offset < 13; ++offset) {
                COUNTER_0X63_DB[offset][index] = 0;
            }
            for (int offset = 0; offset < 16; ++offset) {
                COUNTER_0X63_DC[offset][index] = 0;
            }
            for (int offset = 0; offset < 5; ++offset) {
                COUNTER_0X63_DD[offset][index] = 0;
            }
            for (int offset = 0; offset < 13; ++offset) {
                try {
                    fm.putInt(PRE_COUNTER_0X63_DB + offset + (index + 1), 0);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            for (int offset = 0; offset < 16; ++offset) {
                try {
                    fm.putInt(PRE_COUNTER_0X63_DC + offset + (index + 1), 0);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            for (int offset = 0; offset < 5; ++offset) {
                try {
                    fm.putInt(PRE_COUNTER_0X63_DD + offset + (index + 1), 0);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                fm.putLong(PRE_WEDDING_TIME + (index + 1), 0);
                fm.putLong(PRE_DOFFER_TOTAL_TIME + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DC_1 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DC_5 + (index + 1), 0);
                fm.putInt(PRE_NUMBER_COPS_CHANGE + (index + 1), 0);
                fm.putInt(PRE_YARN_JOINTS + (index + 1), 0);
                fm.putInt(PRE_SPLICE_CYCLES + (index + 1), 0);
                fm.putInt(PRE_SPLICES_RIGHT_FIRST_TIME + (index + 1), 0);
                fm.putLong(PRE_SPLICE_TOTAL_TIME + (index + 1), 0);
                fm.putInt(PRE_SHORT_CUT_COUNTER + (index + 1), 0);
                fm.putInt(PRE_TINY_CUT_COUNTER + (index + 1), 0);
                fm.putInt(PRE_LONG_CUT_COUNTER + (index + 1), 0);
                fm.putInt(PRE_N_CUT_COUNTER + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_4 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_5 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_6 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_7 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_8 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_9 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_10 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_11 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_12 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_13 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_14 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_15 + (index + 1), 0);
                fm.putInt(PRE_BUCKETL_LENGTH + (index + 1), 0);
                fm.putFloat(PRE_BUCKETL_WEIGHT + (index + 1), 0);

            } catch (IOException e) {
                e.printStackTrace();
            }

        }

        long curTime = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
        int start = group.getStartSpindle();
        int end = group.getEndSpindle();

        ObjectBox.get().boxFor(RedLightRecord.class).query().between(RedLightRecord_.spindleId, start, end)
                .greater(RedLightRecord_.start, curTime).build().remove();
        ObjectBox.get().boxFor(ProcessRecord.class).query().between(ProcessRecord_.spindleId, start, end)
                .greater(ProcessRecord_.start, curTime).build().remove();
        ObjectBox.get().boxFor(FaultRecord.class).query().between(FaultRecord_.spindleId, start, end)
                .greater(FaultRecord_.start, curTime).build().remove();
    }

    public void clearGroupReportAuto(int groupNo) {
        Group group = GroupMap.getInstance().getGroupList().get(groupNo - 1);
        int startIndex = group.getStartSpindle() - 1;
        int endIndex = group.getEndSpindle() - 1;

        for (int index = startIndex; index <= endIndex; ++index) {
            WEDDING_TIME[index] = 0;
            DOFFING_TOTAL_TIME[index] = 0;
            PRODUCTION_EFFICIENCY[index] = 0;
            MECHANICAL_EFFICIENCY[index] = 0;
            NUMBER_COPS_CHANGE[index] = 0;
            YARN_JOINTS[index] = 0;
            SHORT_CUT_COUNTER[index] = 0;
            TINY_CUT_COUNTER[index] = 0;
            LONG_CUT_COUNTER[index] = 0;
            N_CUT_COUNTER[index] = 0;
            COUNTER_0X62_DB_4[index] = 0;
            COUNTER_0X62_DB_5[index] = 0;
            COUNTER_0X62_DB_6[index] = 0;
            COUNTER_0X62_DB_7[index] = 0;
            COUNTER_0X62_DB_8[index] = 0;
            COUNTER_0X62_DB_9[index] = 0;
            COUNTER_0X62_DB_10[index] = 0;
            COUNTER_0X62_DB_11[index] = 0;
            COUNTER_0X62_DB_12[index] = 0;
            COUNTER_0X62_DB_13[index] = 0;
            COUNTER_0X62_DB_14[index] = 0;
            COUNTER_0X62_DB_15[index] = 0;
            COUNTER_0X62_DC_10[index] = 0;
            COUNTER_0X62_DC_5[index] = 0;
            SPLICE_CYCLES[index] = 0;
            SPLICES_RIGHT_FIRST_TIME[index] = 0;
            BICKETL_LENGTH[index] = 0;
            BICKETL_WEIGHT[index] = 0;
            SPLICE_TOTAL_TIME[index] = 0;

            for (int offset = 0; offset < 13; ++offset) {
                COUNTER_0X63_DB[offset][index] = 0;
            }
            for (int offset = 0; offset < 16; ++offset) {
                COUNTER_0X63_DC[offset][index] = 0;
            }
            for (int offset = 0; offset < 5; ++offset) {
                COUNTER_0X63_DD[offset][index] = 0;
            }
            for (int offset = 0; offset < 13; ++offset) {
                try {
                    fm.putInt(PRE_COUNTER_0X63_DB + offset + (index + 1), 0);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            for (int offset = 0; offset < 16; ++offset) {
                try {
                    fm.putInt(PRE_COUNTER_0X63_DC + offset + (index + 1), 0);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            for (int offset = 0; offset < 5; ++offset) {
                try {
                    fm.putInt(PRE_COUNTER_0X63_DD + offset + (index + 1), 0);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                fm.putLong(PRE_WEDDING_TIME + (index + 1), 0);
                fm.putLong(PRE_DOFFER_TOTAL_TIME + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DC_1 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DC_5 + (index + 1), 0);
                fm.putInt(PRE_NUMBER_COPS_CHANGE + (index + 1), 0);
                fm.putInt(PRE_YARN_JOINTS + (index + 1), 0);
                fm.putInt(PRE_SPLICE_CYCLES + (index + 1), 0);
                fm.putInt(PRE_SPLICES_RIGHT_FIRST_TIME + (index + 1), 0);
                fm.putLong(PRE_SPLICE_TOTAL_TIME + (index + 1), 0);
                fm.putInt(PRE_SHORT_CUT_COUNTER + (index + 1), 0);
                fm.putInt(PRE_TINY_CUT_COUNTER + (index + 1), 0);
                fm.putInt(PRE_LONG_CUT_COUNTER + (index + 1), 0);
                fm.putInt(PRE_N_CUT_COUNTER + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_4 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_5 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_6 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_7 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_8 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_9 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_10 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_11 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_12 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_13 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_14 + (index + 1), 0);
                fm.putInt(PRE_COUNTER_0X62_DB_15 + (index + 1), 0);
                fm.putInt(PRE_BUCKETL_LENGTH + (index + 1), 0);
                fm.putFloat(PRE_BUCKETL_WEIGHT + (index + 1), 0);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

    public void clearAllReportManual() {
        List<Group> groups = GroupMap.getInstance().getGroupList();
        for (int i = 1; i <= groups.size(); ++i) {
            clearGroupReportManual(i);
        }
        running_time = 0;
        try {
            fm.putLong(STR_RUNNING_TIME, 0);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void clearAllReportAuto() {
        List<Group> groups = GroupMap.getInstance().getGroupList();
        for (int i = 1; i <= groups.size(); ++i) {
            clearGroupReportAuto(i);
        }
        running_time = 0;
        try {
            fm.putLong(STR_RUNNING_TIME, 0);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void clearParaToZero() {
        succeeded_doffer_number = 0;
        dofferdoffing_total_number = 0;
        doffing_total_number = 0;
        running_time = 0;
        try {
            fm.putInt(STR_SUCCEEDED_DOFFER_NUMBER, 0);
            fm.putInt(STR_DOFFERDOFFING_TOTAL_NUMBER, 0);
            fm.putInt(STR_DOFFING_TOTAL_NUMBER, 0);
            fm.putLong(STR_RUNNING_TIME, 0);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void parse77Cmd(int db) {
        new_dofferdoffing_total_number = db;
        if (new_dofferdoffing_total_number > old_dofferdoffing_total_number) {
            int delta = new_dofferdoffing_total_number - old_dofferdoffing_total_number;
            dofferdoffing_total_number += delta;
        }
        old_dofferdoffing_total_number = new_dofferdoffing_total_number;
        try {
            fm.putInt(STR_OLD_DOFFERDOFFING_TOTAL_NUMBER, old_dofferdoffing_total_number);
            fm.putInt(STR_DOFFERDOFFING_TOTAL_NUMBER, dofferdoffing_total_number);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public class WeddingTimeRecorder {
        private boolean[] isRunning = new boolean[72];
        private boolean isMachineRunning;

        private WeddingTimeRecorder() {
            Observable.interval(8, TimeUnit.SECONDS).subscribe(new Consumer<Long>() {
                @Override
                public void accept(Long aLong) throws Throwable {
                    long curTick = System.currentTimeMillis();
                    int spindleCnt = GroupMap.getInstance().getSpindleCount();
                    for (int i = 0; i < spindleCnt; ++i) {
                        if (isRunning[i]) {
                            if (wedding_time_start[i] != 0) {
                                long val = curTick - wedding_time_start[i];
                                if (val > 0 && val < 60 * 1000) {
                                    try {
                                        WEDDING_TIME[i] += val;
                                        fm.putLong(PRE_WEDDING_TIME + (i + 1), WEDDING_TIME[i]);
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
                            wedding_time_start[i] = curTick;
                        }
                        calcEfficiency(i);
                    }
                    if (isMachineRunning) {
                        if (running_time_start != 0) {
                            long val = curTick - running_time_start;
                            if (val > 0 && val < 60 * 1000) {
                                running_time += val;
                                fm.putLong(STR_RUNNING_TIME, running_time);
                            }
                        }
                        running_time_start = curTick;
                    }
                }
            });
        }

        public void start(int spindle) {
            isRunning[spindle] = true;
            wedding_time_start[spindle] = System.currentTimeMillis();
        }

        public void machineStart() {
            isMachineRunning = true;
            running_time_start = System.currentTimeMillis();
        }

        public void stop(int spindle) {
            isRunning[spindle] = false;
            wedding_time_start[spindle] = 0;
            try {
                fm.putLong(PRE_WEDDING_TIME + (spindle + 1), WEDDING_TIME[spindle]);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public void machineStop() {
            isMachineRunning = false;
            running_time_start = 0;
            try {
                fm.putLong(STR_RUNNING_TIME, running_time);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public CbfReport getCurrentCBFDoffer(long time) {
        CbfReport report = cbfBox.query().equal(CbfReport_.start, time).build().findFirst();
        if (report == null) {
            return getTailCBFDoffer();
        }
        return report;
    }

    public HeadReport getTailHeadReport() {
        HeadReport report = new HeadReport();
        report.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
        report.end = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftEndTime());
        report.shiftNum = Integer.valueOf(ShiftTimeRule.getInstance().getCurrentShiftNum());
        report.runningTime = Report.getInstance().getRunningTime();
        return report;
    }

    public ShiftReport getTailSumProduction() {
        int spindleCnt = GroupMap.getInstance().getSpindleCount();
        ShiftReport sum = new ShiftReport();

        //合计值
        for (int i = 1; i <= spindleCnt; i++) {
            sum.windingTime += Report.getInstance().getWeddingTime(i);
            sum.copChangeCount += Report.getInstance().getNumberCopsChange(i);
            sum.yarnJointCount += Report.getInstance().getYarnJoints(i);
            sum.yarnJointCountPer10Km += Report.getInstance().getYarnJointsDiv10(i);
            sum.yarnJointCountPerPackage += Report.getInstance().getYarnJointsDivPackage(i);
            sum.cutCount += Report.getInstance().getNumberCutOfFaults(i);
            sum.cutCountPer10Km += Report.getInstance().getNumberCutOfFaultsDiv10(i);
            sum.cutCountPerCop += Report.getInstance().getnumberCutOfFaultsDivCop(i);
            sum.cutCountPerPackage += Report.getInstance().getnumberCutOfFaultsDivPackage(i);
            sum.packageCount += Report.getInstance().getDofingSpindleAmount(i);
            sum.succeedDoffingPackageCount += Report.getInstance().getSucceededSpindleDofferNumber(i);
            sum.spliceCount += Report.getInstance().getSpliceCycles(i);
            sum.splicesCountRightFirstTime += Report.getInstance().getSplicesRightFirstTime(i);
            sum.production += Report.getInstance().getBucketWeight(i);
            sum.runEfficiency += Report.getInstance().getSpindleProductionEfficiency(i);
            sum.mechanicalEfficiency += Report.getInstance().getSpindleMechanicalEfficiency(i);
            sum.doffingTime += Report.getInstance().get_doffing_total_time(i);
            sum.spliceTime += Report.getInstance().getSpliceTotalTime(i);
        }
        sum.yarnJointCountPer10Km /= spindleCnt;
        sum.yarnJointCountPerPackage /= spindleCnt;
        sum.cutCountPer10Km /= spindleCnt;
        sum.cutCountPerCop /= spindleCnt;
        sum.cutCountPerPackage /= spindleCnt;
        sum.runEfficiency /= spindleCnt;
        sum.mechanicalEfficiency /= spindleCnt;

        sum.type = AppContext.getInstance().getResources().getString(R.string.sum);
        sum.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
        sum.end = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftEndTime());
        sum.shiftNum = Integer.valueOf(ShiftTimeRule.getInstance().getCurrentShiftNum());
        sum.operator = ShiftTimeRule.getInstance().getOperator();
        sum.team = ShiftTimeRule.getInstance().getShiftTeam();

        return sum;

    }

    public ShiftReport getTailAvgProduction() {
        int spindleCnt = GroupMap.getInstance().getSpindleCount();
        ShiftReport avg = new ShiftReport();

        for (int i = 1; i <= spindleCnt; i++) {
            avg.windingTime += Report.getInstance().getWeddingTime(i);
            avg.copChangeCount += Report.getInstance().getNumberCopsChange(i);
            avg.yarnJointCount += Report.getInstance().getYarnJoints(i);
            avg.yarnJointCountPer10Km += Report.getInstance().getYarnJointsDiv10(i);
            avg.yarnJointCountPerPackage += Report.getInstance().getYarnJointsDivPackage(i);
            avg.cutCount += Report.getInstance().getNumberCutOfFaults(i);
            avg.cutCountPer10Km += Report.getInstance().getNumberCutOfFaultsDiv10(i);
            avg.cutCountPerCop += Report.getInstance().getnumberCutOfFaultsDivCop(i);
            avg.cutCountPerPackage += Report.getInstance().getnumberCutOfFaultsDivPackage(i);
            avg.packageCount += Report.getInstance().getDofingSpindleAmount(i);
            avg.succeedDoffingPackageCount += Report.getInstance().getSucceededSpindleDofferNumber(i);
            avg.spliceCount += Report.getInstance().getSpliceCycles(i);
            avg.splicesCountRightFirstTime += Report.getInstance().getSplicesRightFirstTime(i);
            avg.production += Report.getInstance().getBucketWeight(i);
            avg.runEfficiency += Report.getInstance().getSpindleProductionEfficiency(i);
            avg.mechanicalEfficiency += Report.getInstance().getSpindleMechanicalEfficiency(i);
            avg.doffingTime += Report.getInstance().get_doffing_total_time(i);
            avg.spliceTime += Report.getInstance().getSpliceTotalTime(i);
        }
        avg.windingTime /= spindleCnt;
        avg.copChangeCount /= spindleCnt;
        avg.yarnJointCount /= spindleCnt;
        avg.yarnJointCountPer10Km /= spindleCnt;
        avg.yarnJointCountPerPackage /= spindleCnt;
        avg.cutCount /= spindleCnt;
        avg.cutCountPer10Km /= spindleCnt;
        avg.cutCountPerCop /= spindleCnt;
        avg.cutCountPerPackage /= spindleCnt;
        avg.packageCount /= spindleCnt;
        avg.succeedDoffingPackageCount /= spindleCnt;
        avg.spliceCount /= spindleCnt;
        avg.splicesCountRightFirstTime /= spindleCnt;
        avg.production /= spindleCnt;
        avg.runEfficiency /= spindleCnt;
        avg.mechanicalEfficiency /= spindleCnt;
        avg.doffingTime /= spindleCnt;
        avg.spliceTime /= spindleCnt;

        avg.type = AppContext.getInstance().getResources().getString(R.string.average);
        avg.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
        avg.end = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftEndTime());
        avg.shiftNum = Integer.valueOf(ShiftTimeRule.getInstance().getCurrentShiftNum());
        avg.operator = ShiftTimeRule.getInstance().getOperator();
        avg.team = ShiftTimeRule.getInstance().getShiftTeam();

        return avg;

    }

    public List<ShiftReport> getTailGroupProduction() {
        List<Group> groups = GroupMap.getInstance().getGroupList();
        List<ShiftReport> grpList = new ArrayList<>();

        for (int x = 0; x < groups.size(); ++x) {
            int start = groups.get(x).getStartSpindle();
            int end = groups.get(x).getEndSpindle();
            ShiftReport grp = new ShiftReport();

            for (int i = start; i <= end; i++) {
                grp.windingTime += Report.getInstance().getWeddingTime(i);
                grp.copChangeCount += Report.getInstance().getNumberCopsChange(i);
                grp.yarnJointCount += Report.getInstance().getYarnJoints(i);
                grp.yarnJointCountPer10Km += Report.getInstance().getYarnJointsDiv10(i);
                grp.yarnJointCountPerPackage += Report.getInstance().getYarnJointsDivPackage(i);
                grp.cutCount += Report.getInstance().getNumberCutOfFaults(i);
                grp.cutCountPer10Km += Report.getInstance().getNumberCutOfFaultsDiv10(i);
                grp.cutCountPerCop += Report.getInstance().getnumberCutOfFaultsDivCop(i);
                grp.cutCountPerPackage += Report.getInstance().getnumberCutOfFaultsDivPackage(i);
                grp.packageCount += Report.getInstance().getDofingSpindleAmount(i);
                grp.succeedDoffingPackageCount += Report.getInstance().getSucceededSpindleDofferNumber(i);
                grp.spliceCount += Report.getInstance().getSpliceCycles(i);
                grp.splicesCountRightFirstTime += Report.getInstance().getSplicesRightFirstTime(i);
                grp.production += Report.getInstance().getBucketWeight(i);
                grp.runEfficiency += Report.getInstance().getSpindleProductionEfficiency(i);
                grp.mechanicalEfficiency += Report.getInstance().getSpindleMechanicalEfficiency(i);
                grp.doffingTime += Report.getInstance().get_doffing_total_time(i);
                grp.spliceTime += Report.getInstance().getSpliceTotalTime(i);
            }
            int spindleCnt = groups.get(x).getSpindles().size();
            grp.yarnJointCountPer10Km /= spindleCnt;
            grp.yarnJointCountPerPackage /= spindleCnt;
            grp.cutCountPer10Km /= spindleCnt;
            grp.cutCountPerCop /= spindleCnt;
            grp.cutCountPerPackage /= spindleCnt;
            grp.runEfficiency /= spindleCnt;
            grp.mechanicalEfficiency /= spindleCnt;

            grp.type = AppContext.getInstance().getResources().getString(R.string.group) + (x + 1);
            grp.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
            grp.end = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftEndTime());
            grp.shiftNum = Integer.valueOf(ShiftTimeRule.getInstance().getCurrentShiftNum());
            grp.operator = ShiftTimeRule.getInstance().getOperator();
            grp.team = ShiftTimeRule.getInstance().getShiftTeam();
            grpList.add(grp);
        }


        return grpList;
    }

    public List<ShiftReport> getTailSpindleProduction() {
        List<ShiftReport> spindleList = new ArrayList<>();

        int spindleCnt = GroupMap.getInstance().getSpindleCount();
        for (int i = 1; i <= spindleCnt; ++i) {
            ShiftReport spin = new ShiftReport();

            spin.windingTime += Report.getInstance().getWeddingTime(i);
            spin.copChangeCount += Report.getInstance().getNumberCopsChange(i);
            spin.yarnJointCount += Report.getInstance().getYarnJoints(i);
            spin.yarnJointCountPer10Km += Report.getInstance().getYarnJointsDiv10(i);
            spin.yarnJointCountPerPackage += Report.getInstance().getYarnJointsDivPackage(i);
            spin.cutCount += Report.getInstance().getNumberCutOfFaults(i);
            spin.cutCountPer10Km += Report.getInstance().getNumberCutOfFaultsDiv10(i);
            spin.cutCountPerCop += Report.getInstance().getnumberCutOfFaultsDivCop(i);
            spin.cutCountPerPackage += Report.getInstance().getnumberCutOfFaultsDivPackage(i);
            spin.packageCount += Report.getInstance().getDofingSpindleAmount(i);
            spin.succeedDoffingPackageCount += Report.getInstance().getSucceededSpindleDofferNumber(i);
            spin.spliceCount += Report.getInstance().getSpliceCycles(i);
            spin.splicesCountRightFirstTime += Report.getInstance().getSplicesRightFirstTime(i);
            spin.production += Report.getInstance().getBucketWeight(i);
            spin.runEfficiency += Report.getInstance().getSpindleProductionEfficiency(i);
            spin.mechanicalEfficiency += Report.getInstance().getSpindleMechanicalEfficiency(i);
            spin.doffingTime += Report.getInstance().get_doffing_total_time(i);
            spin.spliceTime += Report.getInstance().getSpliceTotalTime(i);

            spin.type = String.valueOf(i);
            spin.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
            spin.end = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftEndTime());
            spin.shiftNum = Integer.valueOf(ShiftTimeRule.getInstance().getCurrentShiftNum());
            spin.operator = ShiftTimeRule.getInstance().getOperator();
            spin.team = ShiftTimeRule.getInstance().getShiftTeam();
            spindleList.add(spin);
        }
        return spindleList;
    }

    public StatisticRecord getTailSumStatistic() {
        StatisticRecord record = new StatisticRecord();
        int spindleCnt = GroupMap.getInstance().getSpindleCount();

        //合计值
        for (int i = 1; i <= spindleCnt; i++) {
            record.spliceCount += Report.getInstance().getYarnJoints(i);
            record.spliceTime += Report.getInstance().getSpliceTotalTime(i);
            record.packageCount += Report.getInstance().getDofingSpindleAmount(i);
            record.dofferTime += Report.getInstance().get_doffing_total_time(i);
        }
        record.spliceTime /= 1000;
        record.dofferTime /= 1000;
        if (record.spliceCount != 0) {
            record.spliceAvgTime = (long) (record.spliceTime / record.spliceCount);
        }
        if (record.packageCount != 0) {
            record.dofferAvgTime = (long) (record.dofferTime / record.packageCount);
        }

        Box<RedLightRecord> redLightBox = ObjectBox.get().boxFor(RedLightRecord.class);
        long start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
        record.redLightCount = redLightBox.query().greater(RedLightRecord_.start, start).build().count();
        record.redLightTime = redLightBox.query().greater(RedLightRecord_.start, start).build().property(RedLightRecord_.duration).sum() / 1000;

        if (record.redLightCount > 0) {
            record.redLightAvgTime = (long) (record.redLightTime / record.redLightCount);
        }

        Box<ProcessRecord> processBox = ObjectBox.get().boxFor(ProcessRecord.class);
        record.processCount = processBox.query().greater(ProcessRecord_.start, start).build().count();
        record.processTime = processBox.query().greater(ProcessRecord_.start, start).build().property(ProcessRecord_.duration).sum() / 1000;

        if (record.processCount > 0) {
            record.processAvgTime = (long) (record.processTime / record.processCount);
        }

        Box<FaultRecord> faultBox = ObjectBox.get().boxFor(FaultRecord.class);
        record.faultCount = faultBox.query().greater(FaultRecord_.start, start).build().count();
        record.faultTime = faultBox.query().greater(FaultRecord_.start, start).build().property(FaultRecord_.duration).sum() / 1000;

        if (record.faultCount > 0) {
            record.faultAvgTime = (long) (record.faultTime / record.faultCount);
        }

        record.type = AppContext.getInstance().getResources().getString(R.string.sum);
        record.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
        record.end = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftEndTime());
        record.operator = ShiftTimeRule.getInstance().getOperator();
        record.team = ShiftTimeRule.getInstance().getShiftTeam();
        return record;
    }

    public StatisticRecord getTailAvgStatistic() {
        StatisticRecord record = new StatisticRecord();
        int spindleCnt = GroupMap.getInstance().getSpindleCount();

        //合计值
        for (int i = 1; i <= spindleCnt; i++) {
            record.spliceCount += Report.getInstance().getYarnJoints(i);
            record.spliceTime += Report.getInstance().getSpliceTotalTime(i);
            record.packageCount += Report.getInstance().getDofingSpindleAmount(i);
            record.dofferTime += Report.getInstance().get_doffing_total_time(i);
        }
        record.spliceCount /= spindleCnt;
        record.spliceTime = record.spliceTime / 1000 / spindleCnt;
        if (record.spliceCount != 0) {
            record.spliceAvgTime = (long) (record.spliceTime / record.spliceCount);
        }

        record.packageCount /= spindleCnt;
        record.dofferTime = record.dofferTime / 1000 / spindleCnt;
        if (record.packageCount != 0) {
            record.dofferAvgTime = (long) (record.dofferTime / record.packageCount);
        }

        Box<RedLightRecord> redLightBox = ObjectBox.get().boxFor(RedLightRecord.class);
        long start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
        record.redLightCount = redLightBox.query().greater(RedLightRecord_.start, start).build().count();
        record.redLightTime = redLightBox.query().greater(RedLightRecord_.start, start).build().property(RedLightRecord_.duration).sum() / 1000;

        if (record.redLightCount > 0) {
            record.redLightCount = record.redLightCount / spindleCnt;
            record.redLightTime = record.redLightTime / spindleCnt;
            record.redLightAvgTime = (long) (record.redLightTime / record.redLightCount);
        }

        Box<ProcessRecord> processBox = ObjectBox.get().boxFor(ProcessRecord.class);
        record.processCount = processBox.query().greater(ProcessRecord_.start, start).build().count();
        record.processTime = processBox.query().greater(ProcessRecord_.start, start).build().property(ProcessRecord_.duration).sum() / 1000;

        if (record.processCount > 0) {
            record.processCount = record.processCount / spindleCnt;
            record.processTime = record.processTime / spindleCnt;
            record.processAvgTime = (long) (record.processTime / record.processCount);
        }

        Box<FaultRecord> faultBox = ObjectBox.get().boxFor(FaultRecord.class);
        record.faultCount = faultBox.query().greater(FaultRecord_.start, start).build().count();
        record.faultTime = faultBox.query().greater(FaultRecord_.start, start).build().property(FaultRecord_.duration).sum() / 1000;

        if (record.faultCount > 0) {
            HashMap<String, String> mapFaultAvgTime = new HashMap<String, String>();
            record.faultCount = record.faultCount / spindleCnt;
            record.faultTime = record.faultTime / spindleCnt;
            record.faultAvgTime = (long) (record.faultTime / record.faultCount);
        }
        record.type = AppContext.getInstance().getResources().getString(R.string.average);
        record.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
        record.end = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftEndTime());
        record.operator = ShiftTimeRule.getInstance().getOperator();
        record.team = ShiftTimeRule.getInstance().getShiftTeam();
        return record;
    }

    public ArrayList<StatisticRecord> getTailGroupStatistic() {
        ArrayList<StatisticRecord> listGroup = new ArrayList<>();
        List<Group> groups = GroupMap.getInstance().getGroupList();
        for (int x = 0; x < groups.size(); ++x) {
            int startSpindle = groups.get(x).getStartSpindle();
            int endSpindle = groups.get(x).getEndSpindle();
            StatisticRecord record = new StatisticRecord();

            //合计值
            for (int i = startSpindle; i <= endSpindle; i++) {
                record.spliceCount += Report.getInstance().getYarnJoints(i);
                record.spliceTime += Report.getInstance().getSpliceTotalTime(i);
                record.packageCount += Report.getInstance().getDofingSpindleAmount(i);
                record.dofferTime += Report.getInstance().get_doffing_total_time(i);
            }
            record.spliceTime /= 1000;
            record.dofferTime /= 1000;
            if (record.spliceCount != 0) {
                record.spliceAvgTime = (long) (record.spliceTime / record.spliceCount);
            }
            if (record.packageCount != 0) {
                record.dofferAvgTime = (long) (record.dofferTime / record.packageCount);
            }

            Box<RedLightRecord> redLightBox = ObjectBox.get().boxFor(RedLightRecord.class);
            long start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
            record.redLightCount = redLightBox.query().greater(RedLightRecord_.start, start).between(RedLightRecord_.spindleId, startSpindle, endSpindle).build().count();
            record.redLightTime = redLightBox.query().greater(RedLightRecord_.start, start).between(RedLightRecord_.spindleId, startSpindle, endSpindle).build().property(RedLightRecord_.duration).sum() / 1000;

            if (record.redLightCount > 0) {
                record.redLightAvgTime = (long) (record.redLightTime / record.redLightCount);
            }

            Box<ProcessRecord> processBox = ObjectBox.get().boxFor(ProcessRecord.class);
            record.processCount = processBox.query().greater(ProcessRecord_.start, start).between(ProcessRecord_.spindleId, startSpindle, endSpindle).build().count();
            record.processTime = processBox.query().greater(ProcessRecord_.start, start).between(ProcessRecord_.spindleId, startSpindle, endSpindle).build().property(ProcessRecord_.duration).sum() / 1000;

            if (record.processCount > 0) {
                record.processAvgTime = (long) (record.processTime / record.processCount);
            }

            Box<FaultRecord> faultBox = ObjectBox.get().boxFor(FaultRecord.class);
            record.faultCount = faultBox.query().greater(FaultRecord_.start, start).between(FaultRecord_.spindleId, startSpindle, endSpindle).build().count();
            record.faultTime = faultBox.query().greater(FaultRecord_.start, start).between(FaultRecord_.spindleId, startSpindle, endSpindle).build().property(FaultRecord_.duration).sum() / 1000;

            if (record.faultCount > 0) {
                record.faultAvgTime = (long) (record.faultTime / record.faultCount);
            }

            record.type = AppContext.getInstance().getResources().getString(R.string.group) + (x + 1);
            record.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
            record.end = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftEndTime());
            record.operator = ShiftTimeRule.getInstance().getOperator();
            record.team = ShiftTimeRule.getInstance().getShiftTeam();

            listGroup.add(record);
        }


        return listGroup;
    }

    public ArrayList<StatisticRecord> getTailSpindleStatistic() {
        int spindleCnt = GroupMap.getInstance().getSpindleCount();
        ArrayList<StatisticRecord> listSpindle = new ArrayList<>();

        for (int spindle = 1; spindle <= spindleCnt; ++spindle) {
            StatisticRecord record = new StatisticRecord();

            record.spliceCount = Report.getInstance().getYarnJoints(spindle);
            record.spliceTime = Report.getInstance().getSpliceTotalTime(spindle);
            record.packageCount = Report.getInstance().getDofingSpindleAmount(spindle);
            record.dofferTime = Report.getInstance().get_doffing_total_time(spindle);
            record.spliceTime /= 1000;
            record.dofferTime /= 1000;
            record.spliceAvgTime = record.spliceCount != 0 ? (long) (record.spliceTime / record.spliceCount) : 0;
            record.dofferAvgTime = record.packageCount != 0 ? (long) (record.dofferTime / record.packageCount) : 0;

            Box<RedLightRecord> redLightBox = ObjectBox.get().boxFor(RedLightRecord.class);
            long start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
            record.redLightCount = redLightBox.query().greater(RedLightRecord_.start, start).equal(RedLightRecord_.spindleId, spindle).build().count();
            record.redLightTime = redLightBox.query().greater(RedLightRecord_.start, start).equal(RedLightRecord_.spindleId, spindle).build().property(RedLightRecord_.duration).sum() / 1000;

            if (record.redLightCount > 0) {
                record.redLightAvgTime = (long) (record.redLightTime / record.redLightCount);
            }

            Box<ProcessRecord> processBox = ObjectBox.get().boxFor(ProcessRecord.class);
            record.processCount = processBox.query().greater(ProcessRecord_.start, start).equal(ProcessRecord_.spindleId, spindle).build().count();
            record.processTime = processBox.query().greater(ProcessRecord_.start, start).equal(ProcessRecord_.spindleId, spindle).build().property(ProcessRecord_.duration).sum() / 1000;

            if (record.processCount > 0) {
                record.processAvgTime = (long) (record.processTime / record.processCount);
            }

            Box<FaultRecord> faultBox = ObjectBox.get().boxFor(FaultRecord.class);
            record.faultCount = faultBox.query().greater(FaultRecord_.start, start).equal(FaultRecord_.spindleId, spindle).build().count();
            record.faultTime = faultBox.query().greater(FaultRecord_.start, start).equal(FaultRecord_.spindleId, spindle).build().property(FaultRecord_.duration).sum() / 1000;

            if (record.faultCount > 0) {
                record.faultAvgTime = (long) (record.faultTime / record.faultCount);
            }

            record.type = String.valueOf(spindle);
            record.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
            record.end = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftEndTime());
            record.operator = ShiftTimeRule.getInstance().getOperator();
            record.team = ShiftTimeRule.getInstance().getShiftTeam();

            listSpindle.add(record);
        }

        return listSpindle;
    }

    public CbfReport getTailCBFDoffer() {
        CbfReport cbfReport = new CbfReport();
        cbfReport.shiftNum = Integer.valueOf(ShiftTimeRule.getInstance().getCurrentShiftNum());
        cbfReport.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
        cbfReport.end = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftEndTime());
        cbfReport.operator = ShiftTimeRule.getInstance().getOperator();
        cbfReport.team = ShiftTimeRule.getInstance().getShiftTeam();
        cbfReport.enterTubeCountD = fm.getInt(String.valueOf(320), 0);
        cbfReport.emptyTubeCountD = fm.getInt(String.valueOf(321), 0);
        cbfReport.remnantTubeCountD = fm.getInt(String.valueOf(322), 0);
        cbfReport.enterSpindleCountD = fm.getInt(String.valueOf(323), 0);
        cbfReport.joint1PassCountD = fm.getInt(String.valueOf(324), 0);
        cbfReport.joint1SucceedCountD = fm.getInt(String.valueOf(325), 0);
        cbfReport.joint2PassCountD = fm.getInt(String.valueOf(326), 0);
        cbfReport.joint2SucceedCountD = fm.getInt(String.valueOf(327), 0);
        cbfReport.joint3PassCountD = fm.getInt(String.valueOf(328), 0);
        cbfReport.joint3SucceedCountD = fm.getInt(String.valueOf(329), 0);
        cbfReport.pullTubeCount = fm.getInt(String.valueOf(330), 0);

        if (MachineParameterSharedPreference.getInstance()
                .getValue(MachineParameterSharedPreference.MACHINE_SPINNINGIN_TYPE, "0").equals("1")) {//双生头
            int denominator = cbfReport.pullTubeCount + cbfReport.joint2SucceedCountD - cbfReport.joint2PassCountD;// 拔管处通过数+第二生头成功数-第二生头通过数
            if (denominator != 0) {
                cbfReport.emptyTubeRatioD = cbfReport.emptyTubeCountD * 100.0f / denominator;
                cbfReport.remnantTubeRatioD = cbfReport.remnantTubeCountD * 100.0f / denominator;
            }
        } else {
            int denominator = cbfReport.pullTubeCount + cbfReport.joint3SucceedCountD - cbfReport.joint3PassCountD;// 拔管处通过数+第三生头成功数-第三生头通过数
            if (denominator != 0) {
                cbfReport.emptyTubeRatioD = cbfReport.emptyTubeCountD * 100.0f / denominator;
                cbfReport.remnantTubeRatioD = cbfReport.remnantTubeCountD * 100.0f / denominator;
            }
        }

        if (cbfReport.joint1PassCountD != 0) {
            cbfReport.joint1SucceedRatioD = cbfReport.joint1SucceedCountD * 100.0f / cbfReport.joint1PassCountD;
        }
        if (cbfReport.joint2PassCountD != 0) {
            cbfReport.joint2SucceedRatioD = cbfReport.joint2SucceedCountD * 100.0f / cbfReport.joint2PassCountD;
        }
        if (cbfReport.joint3PassCountD != 0) {
            cbfReport.joint3SucceedRatioD = cbfReport.joint3SucceedCountD * 100.0f / cbfReport.joint3PassCountD;
        }
        //细络联
        cbfReport.enterTubeCountX = fm.getInt(String.valueOf(300), 0);
        cbfReport.channel1SucceedCountX = fm.getInt(String.valueOf(301), 0);
        cbfReport.channel1FailedCountX = fm.getInt(String.valueOf(302), 0);
        int totalCount = cbfReport.channel1SucceedCountX + cbfReport.channel1FailedCountX;
        if (totalCount != 0) {
            cbfReport.channel1SucceedRatioX = cbfReport.channel1SucceedCountX * 100.0f / totalCount;
        }
        cbfReport.channel2SucceedCountX = fm.getInt(String.valueOf(311), 0);
        cbfReport.channel2FailedCountX = fm.getInt(String.valueOf(312), 0);
        totalCount = cbfReport.channel2SucceedCountX + cbfReport.channel2FailedCountX;
        if (totalCount != 0) {
            cbfReport.channel2SucceedRatioX = cbfReport.channel2SucceedCountX * 100.0f / totalCount;
        }
        cbfReport.emptyTubeCountX = fm.getInt(String.valueOf(303), 0);
        cbfReport.remnantTubeCountX = fm.getInt(String.valueOf(304), 0);
        totalCount = cbfReport.emptyTubeCountX + cbfReport.remnantTubeCountX;
        if (totalCount != 0) {
            cbfReport.emptyTubeRatioX = cbfReport.emptyTubeCountX * 100.0f / totalCount;
            cbfReport.remnantTubeRatioX = cbfReport.remnantTubeCountX * 100.0f / totalCount;
        }

        // 落纱小车
        cbfReport.dofferDoffSucceedCount = Integer.valueOf(Report.getInstance().getSucceededDofferNumber());
        cbfReport.dofferDoffCount = Integer.valueOf(Report.getInstance().getDofferDoffingTotalNumber());
        cbfReport.dofferSucceedRatio = Float.valueOf(Report.getInstance().getSucceededDofferRatio());
        cbfReport.doffCount = Integer.valueOf(Report.getInstance().getDoffingTotalNumber());
        cbfReport.doffSucceedRatio = Float.valueOf(Report.getInstance().getSucceededRatio());
        return cbfReport;
    }

    /**
     * @param time 当前显示时间
     * @param flag "<<":首班 "<":前一班 ">":后一班 ">>":末班 "=":当前时间班次
     * @return
     */
    public long getTime(long time, String flag) {
        if (flag.equals("<<")) {
            return getHeadTime();
        } else if (flag.equals("<")) {
            return getPrevTime(time);
        } else if (flag.equals(">")) {
            return getNextTime(time);
        } else if (flag.equals(">>")) {
            return getTailTime();
        } else if (flag.equals("=")) {
            return time;
        }
        return Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
    }

    public GroupInfo getGroupInfo(long time) {
        GroupInfo info = groupInfoBox.query().equal(GroupInfo_.start, time).build().findFirst();
        if (info == null) {
            info = new GroupInfo();
            List<Group> groups = GroupMap.getInstance().getGroupList();
            info.groupInfo = JSON.toJSONString(groups);
            List<SpindleParameter> parameters = new ArrayList<>();
            for (Group group : groups) {
                long id = group.getId();
                SpindleParameter parameter = ObjectBox.get().boxFor(SpindleParameter.class).get(id);
                parameters.add(parameter);
            }
            info.spindleParameters = JSON.toJSONString(parameters);
        }
        return info;
    }

    public List<ShiftReport> getProduction(long time) {
        List<ShiftReport> list = shiftBox.query().equal(ShiftReport_.start, time).build().find();
        if (list.size() != 0) {
            return list;
        } else {
            list = new ArrayList<>();
            ShiftReport sum = getTailSumProduction();
            ShiftReport avg = getTailAvgProduction();
            List<ShiftReport> grpList = getTailGroupProduction();
            List<ShiftReport> spindleList = getTailSpindleProduction();
            list.add(sum);
            list.add(avg);
            list.addAll(grpList);
            list.addAll(spindleList);
            return list;
        }
    }

    public List<StatisticRecord> getStatistic(long start) {
        List<StatisticRecord> list = statisticBox.query().equal(StatisticRecord_.start, start).build().find();
        if (list.size() != 0) {
            return list;
        } else {
            list = new ArrayList<>();
            StatisticRecord sum = getTailSumStatistic();
            StatisticRecord avg = getTailAvgStatistic();
            List<StatisticRecord> grpList = getTailGroupStatistic();
            List<StatisticRecord> spindleList = getTailSpindleStatistic();
            list.add(sum);
            list.add(avg);
            list.addAll(grpList);
            list.addAll(spindleList);
            return list;
        }

    }

    public List<TubeRecord> getTubeMonitor(long start) {
        Box<TubeRecord> recordBox = ObjectBox.get().boxFor(TubeRecord.class);
        List<TubeRecord> list = recordBox.query().equal(TubeRecord_.start, start).order(TubeRecord_.lastTime).build().find();
        return list;
    }

    public List<TubeRecord4E> getTubeMonitor4E() {
        Box<TubeRecord4E> recordBox = ObjectBox.get().boxFor(TubeRecord4E.class);
        List<TubeRecord4E> list = recordBox.query()
                .equal(TubeRecord4E_.start, Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime())).build().find();
        return list;
    }

    public ShiftReport getBasicInfo(long time) {
        ShiftReport report = shiftBox.query().equal(ShiftReport_.start, time).build().findFirst();
        if (report != null) {
            return report;
        } else {
            return getTailSumProduction();
        }
    }

    public HeadReport getHeadReport(long time) {
        Box<HeadReport> box = ObjectBox.get().boxFor(HeadReport.class);
        HeadReport report = box.query().equal(HeadReport_.start, time).build().findFirst();
        if (report != null) {
            return report;
        } else {
            return getTailHeadReport();
        }
    }

    public long getHeadTime() {
        ShiftReport report = shiftBox.query().build().findFirst();
        if (report != null) {
            return report.start;
        } else {
            return Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
        }
    }

    public long getPrevTime(long time) {
        ShiftReport report = shiftBox.query().less(ShiftReport_.start, time).orderDesc(ShiftReport_.start).build().findFirst();
        if (report != null) {
            return report.start;
        } else {
            return getHeadTime();
        }
    }

    public long getNextTime(long time) {
        ShiftReport report = shiftBox.query().greater(ShiftReport_.start, time).order(ShiftReport_.start).build().findFirst();
        if (report != null) {
            return report.start;
        } else {
            return getTailTime();
        }
    }

    public long getTailTime() {
        return Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
    }

    public List<RedLightCounter> getRedLightLog(long start) {
        Box<RedLightCounter> counterBox = ObjectBox.get().boxFor(RedLightCounter.class);
        List<RedLightCounter> list = counterBox.query().equal(RedLightCounter_.start, start).build().find();
        if (list.size() == 0) {
            return getTailRedLightCounter();
        } else {
            return list;
        }

    }

    public List<RedLightCounter> getTailRedLightCounter() {
        int spindleCnt = GroupMap.getInstance().getSpindleCount();
        int groupCnt = GroupMap.getInstance().getGroupCount();
        List<RedLightCounter> list = new ArrayList<>();

        RedLightCounter sum = new RedLightCounter();
        sum.type = AppContext.getInstance().getResources().getString(R.string.sum);
        sum.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
        sum.count63DC0 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[0]);
        sum.count63DC1 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[1]);
        sum.count63DC2 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[2]);
        sum.count63DC3 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[3]);
        sum.count63DC4 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[4]);
        sum.count63DC15 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[15]);
        list.add(sum);

        for (int i = 0; i < groupCnt; ++i) {
            RedLightCounter grp = new RedLightCounter();
            grp.type = AppContext.getInstance().getResources().getString(R.string.group) + (i + 1);
            grp.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
            grp.count63DC0 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[0], i + 1);
            grp.count63DC1 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[1], i + 1);
            grp.count63DC2 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[2], i + 1);
            grp.count63DC3 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[3], i + 1);
            grp.count63DC4 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[4], i + 1);
            grp.count63DC15 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[15], i + 1);
            list.add(grp);
        }

        for (int i = 0; i < spindleCnt; ++i) {
            RedLightCounter spindle = new RedLightCounter();
            spindle.type = String.valueOf(i + 1);
            spindle.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
            spindle.count63DC0 = Report.getInstance().get0X63DCCounter()[0][i];
            spindle.count63DC1 = Report.getInstance().get0X63DCCounter()[1][i];
            spindle.count63DC2 = Report.getInstance().get0X63DCCounter()[2][i];
            spindle.count63DC3 = Report.getInstance().get0X63DCCounter()[3][i];
            spindle.count63DC4 = Report.getInstance().get0X63DCCounter()[4][i];
            spindle.count63DC15 = Report.getInstance().get0X63DCCounter()[15][i];
            list.add(spindle);
        }

        return list;
    }

    public List<ProcessCounter> getProcessLog(long start) {
        Box<ProcessCounter> counterBox = ObjectBox.get().boxFor(ProcessCounter.class);
        List<ProcessCounter> list = counterBox.query().equal(ProcessCounter_.start, start).build().find();
        if (list.size() == 0) {
            return getTailProcessCounter();
        } else {
            return list;
        }
    }

    public List<ProcessCounter> getTailProcessCounter() {
        int spindleCnt = GroupMap.getInstance().getSpindleCount();
        int groupCnt = GroupMap.getInstance().getGroupCount();
        List<ProcessCounter> list = new ArrayList<>();

        ProcessCounter sum = new ProcessCounter();
        sum.type = AppContext.getInstance().getResources().getString(R.string.sum);
        sum.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
        sum.count63DB0 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[0]);
        sum.count63DB1 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[1]);
        sum.count63DB2 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[2]);
        sum.count63DB3 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[3]);
        sum.count63DB4 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[4]);
        sum.count63DB5 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[5]);
        sum.count63DB6 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[6]);
        sum.count63DB7 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[7]);
        sum.count63DB8 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[8]);
        sum.count63DB9 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[9]);
        sum.count63DB10 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[10]);
        sum.count63DB11 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[11]);
        list.add(sum);

        for (int i = 0; i < groupCnt; ++i) {
            ProcessCounter grp = new ProcessCounter();
            grp.type = AppContext.getInstance().getResources().getString(R.string.group) + (i + 1);
            grp.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
            grp.count63DB0 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[0], i + 1);
            grp.count63DB1 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[1], i + 1);
            grp.count63DB2 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[2], i + 1);
            grp.count63DB3 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[3], i + 1);
            grp.count63DB4 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[4], i + 1);
            grp.count63DB5 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[5], i + 1);
            grp.count63DB6 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[6], i + 1);
            grp.count63DB7 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[7], i + 1);
            grp.count63DB8 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[8], i + 1);
            grp.count63DB9 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[9], i + 1);
            grp.count63DB10 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[10], i + 1);
            grp.count63DB11 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[11], i + 1);
            list.add(grp);
        }

        for (int i = 0; i < spindleCnt; ++i) {
            ProcessCounter spindle = new ProcessCounter();
            spindle.type = String.valueOf(i + 1);
            spindle.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
            spindle.count63DB0 = Report.getInstance().get0X63DBCounter()[0][i];
            spindle.count63DB1 = Report.getInstance().get0X63DBCounter()[1][i];
            spindle.count63DB2 = Report.getInstance().get0X63DBCounter()[2][i];
            spindle.count63DB3 = Report.getInstance().get0X63DBCounter()[3][i];
            spindle.count63DB4 = Report.getInstance().get0X63DBCounter()[4][i];
            spindle.count63DB5 = Report.getInstance().get0X63DBCounter()[5][i];
            spindle.count63DB6 = Report.getInstance().get0X63DBCounter()[6][i];
            spindle.count63DB7 = Report.getInstance().get0X63DBCounter()[7][i];
            spindle.count63DB8 = Report.getInstance().get0X63DBCounter()[8][i];
            spindle.count63DB9 = Report.getInstance().get0X63DBCounter()[9][i];
            spindle.count63DB10 = Report.getInstance().get0X63DBCounter()[10][i];
            spindle.count63DB11 = Report.getInstance().get0X63DBCounter()[11][i];
            list.add(spindle);
        }

        return list;
    }

    public List<FaultCounter> getFaultLog(long start) {
        Box<FaultCounter> box = ObjectBox.get().boxFor(FaultCounter.class);
        List<FaultCounter> list = box.query().equal(FaultCounter_.start, start).build().find();
        if (list.size() == 0) {
            return getTailFaultCounter();
        }
        return list;
    }

    public List<FaultCounter> getTailFaultCounter() {
        int spindleCnt = GroupMap.getInstance().getSpindleCount();
        int groupCnt = GroupMap.getInstance().getGroupCount();
        List<FaultCounter> list = new ArrayList<>();
        FaultCounter sum = new FaultCounter();
        sum.type = AppContext.getInstance().getResources().getString(R.string.sum);
        sum.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
        sum.count63DC5 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[5]);
        sum.count63DC6 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[6]);
        sum.count63DC7 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[7]);
        sum.count63DC8 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[8]);
        sum.count63DC9 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[9]);
        sum.count63DC10 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[10]);
        sum.count63DC11 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[11]);
        sum.count63DC12 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[12]);
        sum.count63DC13 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[13]);
        sum.count63DC14 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[14]);
        sum.count63DD0 = Report.getInstance().getCountSum(Report.getInstance().get0X63DDCounter()[0]);
        sum.count63DD1 = Report.getInstance().getCountSum(Report.getInstance().get0X63DDCounter()[1]);
        sum.count63DD3 = Report.getInstance().getCountSum(Report.getInstance().get0X63DDCounter()[3]);
        sum.count63DD4 = Report.getInstance().getCountSum(Report.getInstance().get0X63DDCounter()[4]);
        sum.count63DB12 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[12]);
        list.add(sum);

        for (int i = 0; i < groupCnt; ++i) {
            FaultCounter grp = new FaultCounter();
            grp.type = AppContext.getInstance().getResources().getString(R.string.group) + (i + 1);
            grp.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
            grp.count63DC5 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[5], i + 1);
            grp.count63DC6 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[6], i + 1);
            grp.count63DC7 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[7], i + 1);
            grp.count63DC8 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[8], i + 1);
            grp.count63DC9 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[9], i + 1);
            grp.count63DC10 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[10], i + 1);
            grp.count63DC11 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[11], i + 1);
            grp.count63DC12 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[12], i + 1);
            grp.count63DC13 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[13], i + 1);
            grp.count63DC14 = Report.getInstance().getCountSum(Report.getInstance().get0X63DCCounter()[14], i + 1);
            grp.count63DD0 = Report.getInstance().getCountSum(Report.getInstance().get0X63DDCounter()[0], i + 1);
            grp.count63DD1 = Report.getInstance().getCountSum(Report.getInstance().get0X63DDCounter()[1], i + 1);
            grp.count63DD3 = Report.getInstance().getCountSum(Report.getInstance().get0X63DDCounter()[3], i + 1);
            grp.count63DD4 = Report.getInstance().getCountSum(Report.getInstance().get0X63DDCounter()[4], i + 1);
            grp.count63DB12 = Report.getInstance().getCountSum(Report.getInstance().get0X63DBCounter()[12], i + 1);
            list.add(grp);
        }

        for (int i = 0; i < spindleCnt; ++i) {
            FaultCounter spindle = new FaultCounter();
            spindle.type = String.valueOf(i + 1);
            spindle.start = Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime());
            spindle.count63DC5 = Report.getInstance().get0X63DCCounter()[5][i];
            spindle.count63DC6 = Report.getInstance().get0X63DCCounter()[6][i];
            spindle.count63DC7 = Report.getInstance().get0X63DCCounter()[7][i];
            spindle.count63DC8 = Report.getInstance().get0X63DCCounter()[8][i];
            spindle.count63DC9 = Report.getInstance().get0X63DCCounter()[9][i];
            spindle.count63DC10 = Report.getInstance().get0X63DCCounter()[10][i];
            spindle.count63DC11 = Report.getInstance().get0X63DCCounter()[11][i];
            spindle.count63DC12 = Report.getInstance().get0X63DCCounter()[12][i];
            spindle.count63DC13 = Report.getInstance().get0X63DCCounter()[13][i];
            spindle.count63DC14 = Report.getInstance().get0X63DCCounter()[14][i];
            spindle.count63DD0 = Report.getInstance().get0X63DDCounter()[0][i];
            spindle.count63DD1 = Report.getInstance().get0X63DDCounter()[1][i];
            spindle.count63DD3 = Report.getInstance().get0X63DDCounter()[3][i];
            spindle.count63DD4 = Report.getInstance().get0X63DDCounter()[4][i];
            spindle.count63DB12 = Report.getInstance().get0X63DBCounter()[12][i];
            list.add(spindle);
        }

        return list;
    }
}